Skip to content
Merged
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
61 changes: 46 additions & 15 deletions sound/soc/sof/ipc4-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -557,12 +557,15 @@ static int sof_ipc4_pcm_hw_free(struct snd_soc_component *component,
return sof_ipc4_trigger_pipelines(component, substream, SOF_IPC4_PIPE_RESET, 0);
}

static void ipc4_ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char *link_name,
struct snd_pcm_hw_params *params)
static int ipc4_ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev,
const char *link_name,
struct snd_pcm_hw_params *params)
{
struct snd_sof_dai_link *slink;
struct snd_sof_dai *dai;
bool dai_link_found = false;
int current_config = -1;
bool partial_match;
int i;

list_for_each_entry(slink, &sdev->dai_link_list, list) {
Expand All @@ -573,19 +576,50 @@ static void ipc4_ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const
}

if (!dai_link_found)
return;
return 0;

/*
* Find the first best matching hardware config:
* rate + format + channels are matching
* rate + channel are matching
*
* The copier cannot do rate and/or channel conversion.
*/
for (i = 0; i < slink->num_hw_configs; i++) {
struct snd_soc_tplg_hw_config *hw_config = &slink->hw_configs[i];

if (params_rate(params) == le32_to_cpu(hw_config->fsync_rate)) {
/* set current config for all DAI's with matching name */
list_for_each_entry(dai, &sdev->dai_list, list)
if (!strcmp(slink->link->name, dai->name))
dai->current_config = le32_to_cpu(hw_config->id);
if (params_rate(params) == le32_to_cpu(hw_config->fsync_rate) &&
params_width(params) == le32_to_cpu(hw_config->tdm_slot_width) &&
params_channels(params) == le32_to_cpu(hw_config->tdm_slots)) {
current_config = le32_to_cpu(hw_config->id);
partial_match = false;
/* best match found */
break;
} else if (current_config < 0 &&
params_rate(params) == le32_to_cpu(hw_config->fsync_rate) &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

Change second level to rate and channels and remove third level? Fail if first or second level match is not found. Copier can convert sample format but not rate and channels count.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

let me think about it a bit, this function was not able to fail before, even if it has not found the config.

Copy link

Choose a reason for hiding this comment

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

There could of course be some simple ranking about the formats if exact match is not found to prefer higher precision over lower, but in practice (only having s32 format available) this hardly matters.

Copy link
Collaborator Author

@ujfalusi ujfalusi Apr 30, 2025

Choose a reason for hiding this comment

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

I think with this we will find the exact match and if no exact config available then we pick the first one which have matching rate and channels. It can be up to debate which non exact match is the best one, but I feel that if we don't have the exact match available then we are already in a 'this is not going to end up right' space..

params_channels(params) == le32_to_cpu(hw_config->tdm_slots)) {
current_config = le32_to_cpu(hw_config->id);
partial_match = true;
/* keep looking for better match */
}
}

if (current_config < 0) {
dev_err(sdev->dev,
"%s: No suitable hw_config found for %s (num_hw_configs: %d)\n",
__func__, slink->link->name, slink->num_hw_configs);
return -EINVAL;
}

dev_dbg(sdev->dev,
"hw_config for %s: %d (num_hw_configs: %d) with %s match\n",
slink->link->name, current_config, slink->num_hw_configs,
partial_match ? "partial" : "full");
list_for_each_entry(dai, &sdev->dai_list, list)
if (!strcmp(slink->link->name, dai->name))
dai->current_config = current_config;

return 0;
}

/*
Expand Down Expand Up @@ -728,13 +762,10 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
break;
}

switch (ipc4_copier->dai_type) {
case SOF_DAI_INTEL_SSP:
ipc4_ssp_dai_config_pcm_params_match(sdev, (char *)rtd->dai_link->name, params);
break;
default:
break;
}
if (ipc4_copier->dai_type == SOF_DAI_INTEL_SSP)
return ipc4_ssp_dai_config_pcm_params_match(sdev,
(char *)rtd->dai_link->name,
params);

return 0;
}
Expand Down
Loading