From d82bf6af621301971ac01b0f2919e87137c59774 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 21 Apr 2026 17:13:51 +0800 Subject: [PATCH] ASoC: SOF: topology: allow user to add topologies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the function topology provides the basic audio function. The commit allow the users add their topologies to the topology list. So they can add their own features. Signed-off-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://patch.msgid.link/20260421091351.4056377-3-yung-chuan.liao@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 55 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 63d582c65891..87b539916b4a 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -23,6 +23,13 @@ static bool disable_function_topology; module_param(disable_function_topology, bool, 0444); MODULE_PARM_DESC(disable_function_topology, "Disable function topology loading"); +#define MAX_FEATURE_TPLG_COUNT 16 + +static char *feature_topologies[MAX_FEATURE_TPLG_COUNT]; +static int feature_tplg_cnt; +module_param_array(feature_topologies, charp, &feature_tplg_cnt, 0444); +MODULE_PARM_DESC(feature_topologies, "Topology list for virtual loop DAI link"); + #define COMP_ID_UNASSIGNED 0xffffffff /* * Constants used in the computation of linear volume gain @@ -2575,6 +2582,54 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file) } } + /* Loading user defined topologies */ + for (i = 0; i < feature_tplg_cnt; i++) { + const char *feature_topology = devm_kasprintf(scomp->dev, GFP_KERNEL, "%s/%s", + tplg_filename_prefix, + feature_topologies[i]); + + if (!feature_topology) { + ret = -ENOMEM; + goto out; + } + dev_info(scomp->dev, "loading feature topology %d: %s\n", i, feature_topology); + ret = request_firmware(&fw, feature_topology, 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_warn(scomp->dev, "feature tplg request firmware %s failed err: %d\n", + feature_topologies[i], ret); + /* + * We don't return error here because we can still have the basic + * audio feature when the function topology load complete. No need + * to convert the error code because we will get new 'ret' out of the + * loop. + */ + continue; + } + + 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, "feature tplg %s component load failed %d\n", + feature_topologies[i], ret); + /* + * We need to return error here because it may lead to kernel NULL pointer + * dereference if we continue the remaining tasks. + */ + goto out; + } + } + /* call sof_complete when topologies are loaded successfully */ ret = sof_complete(scomp);