]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ASoC: SOF: topology: allow user to add topologies
authorBard Liao <yung-chuan.liao@linux.intel.com>
Tue, 21 Apr 2026 09:13:51 +0000 (17:13 +0800)
committerMark Brown <broonie@kernel.org>
Sun, 26 Apr 2026 23:29:01 +0000 (08:29 +0900)
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 <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://patch.msgid.link/20260421091351.4056377-3-yung-chuan.liao@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/topology.c

index 63d582c6589154ad6c420311c26d9965d741e50c..87b539916b4a7cb6d47ddb7b69f9500ff74718e0 100644 (file)
@@ -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);