mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
ASoC: SOF: topology: allow user to add topologies
Bard Liao <yung-chuan.liao@linux.intel.com> says: This series adds a module parameter array to allow users to load specific feature topologies.
This commit is contained in:
commit
0d13279992
|
|
@ -19,6 +19,7 @@ enum tplg_device_id {
|
|||
TPLG_DEVICE_SDCA_MIC,
|
||||
TPLG_DEVICE_INTEL_PCH_DMIC,
|
||||
TPLG_DEVICE_HDMI,
|
||||
TPLG_DEVICE_LOOPBACK_VIRTUAL,
|
||||
TPLG_DEVICE_MAX
|
||||
};
|
||||
|
||||
|
|
@ -81,7 +82,15 @@ int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_
|
|||
} else if (strstr(dai_link->name, "iDisp")) {
|
||||
tplg_dev = TPLG_DEVICE_HDMI;
|
||||
tplg_dev_name = "hdmi-pcm5";
|
||||
|
||||
} else if (strstr(dai_link->name, "Loopback_Virtual")) {
|
||||
tplg_dev = TPLG_DEVICE_LOOPBACK_VIRTUAL;
|
||||
/*
|
||||
* Mark the LOOPBACK_VIRTUAL device but no need to create the
|
||||
* LOOPBACK_VIRTUAL topology. Just to avoid the dai_link is not supported
|
||||
* error.
|
||||
*/
|
||||
tplg_mask |= BIT(tplg_dev);
|
||||
continue;
|
||||
} else {
|
||||
/* The dai link is not supported by separated tplg yet */
|
||||
dev_dbg(card->dev,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user