Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/uapi/sound/sof/tokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
#define SOF_TKN_SCHED_LP_MODE 207
#define SOF_TKN_SCHED_MEM_USAGE 208
#define SOF_TKN_SCHED_USE_CHAIN_DMA 209
#define SOF_TKN_SCHED_KCPS 210
#define SOF_TKN_SCHED_DIRECTION 211
#define SOF_TKN_SCHED_DIRECTION_VALID 212

/* volume */
#define SOF_TKN_VOLUME_RAMP_STEP_TYPE 250
Expand Down
43 changes: 41 additions & 2 deletions sound/soc/intel/boards/sof_sdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,34 @@ static int create_bt_dailinks(struct snd_soc_card *card,
return 0;
}

static int create_echoref_dailink(struct snd_soc_card *card,
struct snd_soc_dai_link **dai_links, int *be_id)
{
struct device *dev = card->dev;
int ret;
char *name = devm_kasprintf(dev, GFP_KERNEL, "Loopback_Virtual");

if (!name)
return -ENOMEM;

/*
* use dummy DAI names as this won't be connected to an actual DAI but just to establish a
* fe <-> be connection for loopback capture for echo reference
*/
ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, name,
0, 1, "snd-soc-dummy-dai", "dummy",
snd_soc_dummy_dlc.name, snd_soc_dummy_dlc.dai_name,
1, NULL, NULL);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only sdw can have this feature, HDA or SSP machines never?
We cannot add to topology a tone generator for example at will, but we need to change the kernel as well?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory the same logic would work for all machines and yes you would need the machine driver change in order to use it. But in the case of SSP, we dont need this. We can use the Loopback mode like we've always used. So maybe just the HDA machine change would be enough

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HDA and SSP not priority.

if (ret)
return ret;

(*dai_links)++;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how this will work with existing topologies and with function topology?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldnt matter if we use function topologies right? We just have a single machine even in that case right?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the function topology parsing will fall back to monolithic when it faces with a link of unknown origin/no fragment.
We have now patch to make this not fail when there is no monolithic topology defined, but this (I think) will eventually disable the function topologies?

I'm not sure, but this is my feeling.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

best to comment what the assumption will be here regarding topology.


dev_dbg(dev, "Added echo reference DAI link\n");

return 0;
}

static int sof_card_dai_links_create(struct snd_soc_card *card)
{
struct device *dev = card->dev;
Expand Down Expand Up @@ -1304,8 +1332,12 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
goto err_end;
}

/* allocate BE dailinks */
num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num;
/*
* allocate BE dailinks, add an extra DAI link for echo reference capture.
* This should be the last DAI link and it is expected both for monolithic
* and functional SOF topologies to support echo reference.
*/
num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num + 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is also a chicken and egg problem... This is purely topology construct, but we don't know if the topology have virtual DAI before we pick and parse the topology and for that we need the links in place if the topology do have this defined, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, lets capture this behavior in the comments.

dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL);
if (!dai_links) {
ret = -ENOMEM;
Expand Down Expand Up @@ -1354,6 +1386,13 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
goto err_end;
}

/* dummy echo ref link. keep this as the last DAI link. The DAI link ID does not matter */
ret = create_echoref_dailink(card, &dai_links, &be_id);
if (ret) {
dev_err(dev, "failed to create echo ref dai link: %d\n", ret);
goto err_end;
}

WARN_ON(codec_conf != card->codec_conf + card->num_configs);
WARN_ON(dai_links != card->dai_link + card->num_links);

Expand Down
62 changes: 49 additions & 13 deletions sound/soc/sof/ipc4-topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ static const struct sof_topology_token ipc4_sched_tokens[] = {
offsetof(struct sof_ipc4_pipeline, core_id)},
{SOF_TKN_SCHED_PRIORITY, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
offsetof(struct sof_ipc4_pipeline, priority)},
{SOF_TKN_SCHED_DIRECTION, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
offsetof(struct sof_ipc4_pipeline, direction)},
{SOF_TKN_SCHED_DIRECTION, SND_SOC_TPLG_TUPLE_TYPE_BOOL, get_token_u16,
offsetof(struct sof_ipc4_pipeline, direction_valid)},
};

static const struct sof_topology_token pipeline_tokens[] = {
Expand Down Expand Up @@ -939,6 +943,10 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)

swidget->core = pipeline->core_id;
spipe->core_mask |= BIT(pipeline->core_id);
if (pipeline->direction_valid) {
spipe->direction = pipeline->direction;
spipe->direction_valid = true;
}

if (pipeline->use_chain_dma) {
dev_dbg(scomp->dev, "Set up chain DMA for %s\n", swidget->widget->name);
Expand All @@ -954,9 +962,9 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
goto err;
}

dev_dbg(scomp->dev, "pipeline '%s': id %d, pri %d, core_id %u, lp mode %d\n",
dev_dbg(scomp->dev, "pipeline '%s': id %d, pri %d, core_id %u, lp mode %d direction %d\n",
swidget->widget->name, swidget->pipeline_id,
pipeline->priority, pipeline->core_id, pipeline->lp_mode);
pipeline->priority, pipeline->core_id, pipeline->lp_mode, pipeline->direction);

swidget->private = pipeline;

Expand Down Expand Up @@ -2745,12 +2753,14 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
int input_fmt_index = 0;
int ret;

input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
&process->base_config,
pipeline_params,
available_fmt);
if (input_fmt_index < 0)
return input_fmt_index;
if (available_fmt->num_input_formats) {
input_fmt_index = sof_ipc4_init_input_audio_fmt(sdev, swidget,
&process->base_config,
pipeline_params,
available_fmt);
if (input_fmt_index < 0)
return input_fmt_index;
}

/* Configure output audio format only if the module supports output */
if (available_fmt->num_output_formats) {
Expand All @@ -2759,12 +2769,28 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
u32 out_ref_rate, out_ref_channels;
int out_ref_valid_bits, out_ref_type;

in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;
if (available_fmt->num_input_formats) {
in_fmt = &available_fmt->input_pin_fmts[input_fmt_index].audio_fmt;

out_ref_rate = in_fmt->sampling_frequency;
out_ref_channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg);
out_ref_rate = in_fmt->sampling_frequency;
out_ref_channels =
SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(in_fmt->fmt_cfg);
out_ref_valid_bits =
SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_fmt->fmt_cfg);
out_ref_type = sof_ipc4_fmt_cfg_to_type(in_fmt->fmt_cfg);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and to add I have this PR for some time which touches the same code and fixes issue when not all parameters are changed by a process module:
#5442

} else {
/* for modules without input formats, use FE params as reference */
out_ref_rate = params_rate(fe_params);
out_ref_channels = params_channels(fe_params);
ret = sof_ipc4_get_sample_type(sdev, fe_params);
if (ret < 0)
return ret;
out_ref_type = (u32)ret;

out_ref_valid_bits = sof_ipc4_get_valid_bits(sdev, fe_params);
if (out_ref_valid_bits < 0)
return out_ref_valid_bits;
}

output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
&process->base_config,
Expand Down Expand Up @@ -2792,6 +2818,16 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget,
if (ret)
return ret;
}

/* set base cfg to match the first output format if there are no input formats */
if (!available_fmt->num_input_formats) {
struct sof_ipc4_audio_format *out_fmt;

out_fmt = &available_fmt->output_pin_fmts[0].audio_fmt;

/* copy output format */
memcpy(&process->base_config.audio_fmt, out_fmt, sizeof(*out_fmt));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what will happen if the fe_parmas and the first output_fmt of the module does not match?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll end up with an error that out format match wasnt found on line 2802 isnt it?

}
}

sof_ipc4_dbg_module_audio_format(sdev->dev, swidget, available_fmt,
Expand Down
4 changes: 4 additions & 0 deletions sound/soc/sof/ipc4-topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ struct sof_ipc4_copier_config_set_sink_format {
* @use_chain_dma: flag to indicate if the firmware shall use chained DMA
* @msg: message structure for pipeline
* @skip_during_fe_trigger: skip triggering this pipeline during the FE DAI trigger
* @direction_valid: flag indicating if valid direction is set in topology
* @direction: pipeline direction set in topology if direction_valid is true
*/
struct sof_ipc4_pipeline {
uint32_t priority;
Expand All @@ -160,6 +162,8 @@ struct sof_ipc4_pipeline {
bool use_chain_dma;
struct sof_ipc4_msg msg;
bool skip_during_fe_trigger;
bool direction_valid;
u32 direction;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be documented what values are valid for direction, like what 0 means, what 1 means, is there a direction == 2...10?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ujfalusi these come directly from topology, so are checked for validity there.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, the value for kernel does not matter, only they should match?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can add that context to the comment. Can complain too if out of range.

};

/**
Expand Down
Loading
Loading