mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
ASoC: SOF: topology: load multiple topologies
Currently, we always use single topology file to describe the widgets. However, with SDCA, we want to be able to load sub-topologies based on the supported device functions. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com> Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> Link: https://patch.msgid.link/20250414063239.85200-5-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
d1e70eed0b
commit
6d5997c412
1 changed files with 68 additions and 18 deletions
|
@ -2310,8 +2310,10 @@ static const struct snd_soc_tplg_ops sof_tplg_ops = {
|
|||
.link_load = sof_link_load,
|
||||
.link_unload = sof_link_unload,
|
||||
|
||||
/* completion - called at completion of firmware loading */
|
||||
.complete = sof_complete,
|
||||
/*
|
||||
* No need to set the complete callback. sof_complete will be called explicitly after
|
||||
* topology loading is complete.
|
||||
*/
|
||||
|
||||
/* manifest - optional to inform component of manifest */
|
||||
.manifest = sof_manifest,
|
||||
|
@ -2467,34 +2469,82 @@ static const struct snd_soc_tplg_ops sof_dspless_tplg_ops = {
|
|||
int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
|
||||
{
|
||||
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
||||
struct snd_sof_pdata *sof_pdata = sdev->pdata;
|
||||
const char *tplg_filename_prefix = sof_pdata->tplg_filename_prefix;
|
||||
const struct firmware *fw;
|
||||
const char **tplg_files;
|
||||
int tplg_cnt = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
dev_dbg(scomp->dev, "loading topology:%s\n", file);
|
||||
tplg_files = kcalloc(scomp->card->num_links, sizeof(char *), GFP_KERNEL);
|
||||
if (!tplg_files)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = request_firmware(&fw, file, scomp->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(scomp->dev, "error: tplg request firmware %s failed err: %d\n",
|
||||
file, ret);
|
||||
dev_err(scomp->dev,
|
||||
"you may need to download the firmware from https://github.com/thesofproject/sof-bin/\n");
|
||||
return ret;
|
||||
if (sof_pdata->machine->get_function_tplg_files) {
|
||||
tplg_cnt = sof_pdata->machine->get_function_tplg_files(scomp->card,
|
||||
sof_pdata->machine,
|
||||
tplg_filename_prefix,
|
||||
&tplg_files);
|
||||
if (tplg_cnt < 0) {
|
||||
kfree(tplg_files);
|
||||
return tplg_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
if (sdev->dspless_mode_selected)
|
||||
ret = snd_soc_tplg_component_load(scomp, &sof_dspless_tplg_ops, fw);
|
||||
else
|
||||
ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw);
|
||||
/*
|
||||
* The monolithic topology will be used if there is no get_function_tplg_files
|
||||
* callback or the callback returns 0.
|
||||
*/
|
||||
if (!tplg_cnt) {
|
||||
tplg_files[0] = file;
|
||||
tplg_cnt = 1;
|
||||
dev_dbg(scomp->dev, "loading topology: %s\n", file);
|
||||
} else {
|
||||
dev_info(scomp->dev, "Using function topologies instead %s\n", file);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
dev_err(scomp->dev, "error: tplg component load failed %d\n",
|
||||
ret);
|
||||
for (i = 0; i < tplg_cnt; i++) {
|
||||
/* Only print the file names if the function topologies are used */
|
||||
if (tplg_files[0] != file)
|
||||
dev_info(scomp->dev, "loading topology %d: %s\n", i, tplg_files[i]);
|
||||
|
||||
release_firmware(fw);
|
||||
ret = request_firmware(&fw, tplg_files[i], scomp->dev);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* snd_soc_tplg_component_remove(scomp) will be called
|
||||
* if snd_soc_tplg_component_load(scomp) failed and all
|
||||
* objects in the scomp will be removed. No need to call
|
||||
* snd_soc_tplg_component_remove(scomp) here.
|
||||
*/
|
||||
dev_err(scomp->dev, "tplg request firmware %s failed err: %d\n",
|
||||
tplg_files[i], ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sdev->dspless_mode_selected)
|
||||
ret = snd_soc_tplg_component_load(scomp, &sof_dspless_tplg_ops, fw);
|
||||
else
|
||||
ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw);
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(scomp->dev, "tplg %s component load failed %d\n",
|
||||
tplg_files[i], ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* call sof_complete when topologies are loaded successfully */
|
||||
ret = sof_complete(scomp);
|
||||
|
||||
out:
|
||||
if (ret >= 0 && sdev->led_present)
|
||||
ret = snd_ctl_led_request();
|
||||
|
||||
kfree(tplg_files);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(snd_sof_load_topology);
|
||||
|
|
Loading…
Add table
Reference in a new issue