mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 03:24:19 +02:00
ASoC: SOF: ipc4-pcm: Look for best matching hw_config for SSP
Instead of just looking for a hw_config with matching rate only it sounds better to try to find the best matching configuration. If we have multiple hw_configurations with the same rate, but each with different format for example then we have been picking the first config with the matching rate, which can be a problem and it wil depend on how the configs are ordered. Instead we should be trying to find the best match out of the configs 1. rate + format + channels are matching 2. rate + format are matching 3. rate matching Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Link: https://patch.msgid.link/20250619102657.12109-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
7f8924e878
commit
8a07944a77
|
|
@ -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);
|
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,
|
static int ipc4_ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev,
|
||||||
struct snd_pcm_hw_params *params)
|
const char *link_name,
|
||||||
|
struct snd_pcm_hw_params *params)
|
||||||
{
|
{
|
||||||
struct snd_sof_dai_link *slink;
|
struct snd_sof_dai_link *slink;
|
||||||
struct snd_sof_dai *dai;
|
struct snd_sof_dai *dai;
|
||||||
bool dai_link_found = false;
|
bool dai_link_found = false;
|
||||||
|
int current_config = -1;
|
||||||
|
bool partial_match;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
list_for_each_entry(slink, &sdev->dai_link_list, list) {
|
list_for_each_entry(slink, &sdev->dai_link_list, list) {
|
||||||
|
|
@ -573,19 +576,50 @@ static void ipc4_ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dai_link_found)
|
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++) {
|
for (i = 0; i < slink->num_hw_configs; i++) {
|
||||||
struct snd_soc_tplg_hw_config *hw_config = &slink->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)) {
|
if (params_rate(params) == le32_to_cpu(hw_config->fsync_rate) &&
|
||||||
/* set current config for all DAI's with matching name */
|
params_width(params) == le32_to_cpu(hw_config->tdm_slot_width) &&
|
||||||
list_for_each_entry(dai, &sdev->dai_list, list)
|
params_channels(params) == le32_to_cpu(hw_config->tdm_slots)) {
|
||||||
if (!strcmp(slink->link->name, dai->name))
|
current_config = le32_to_cpu(hw_config->id);
|
||||||
dai->current_config = le32_to_cpu(hw_config->id);
|
partial_match = false;
|
||||||
|
/* best match found */
|
||||||
break;
|
break;
|
||||||
|
} else if (current_config < 0 &&
|
||||||
|
params_rate(params) == le32_to_cpu(hw_config->fsync_rate) &&
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -728,13 +762,10 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ipc4_copier->dai_type) {
|
if (ipc4_copier->dai_type == SOF_DAI_INTEL_SSP)
|
||||||
case SOF_DAI_INTEL_SSP:
|
return ipc4_ssp_dai_config_pcm_params_match(sdev,
|
||||||
ipc4_ssp_dai_config_pcm_params_match(sdev, (char *)rtd->dai_link->name, params);
|
(char *)rtd->dai_link->name,
|
||||||
break;
|
params);
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user