summaryrefslogtreecommitdiff
path: root/sound/soc/sof/topology.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2022-07-15 17:11:58 +0300
committerTakashi Iwai <tiwai@suse.de>2022-07-15 17:11:58 +0300
commit29a249d72d31cde3cd24d43354b40019efdb48b1 (patch)
tree7b8b353a958b18e72ba14271dbd60f022fab2336 /sound/soc/sof/topology.c
parentffb2759df7efbc00187bfd9d1072434a13a54139 (diff)
parent7fb72b7bf167a8047204d30e0e8affe6023363d9 (diff)
downloadlinux-29a249d72d31cde3cd24d43354b40019efdb48b1.tar.xz
Merge tag 'asoc-v5.20' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next
ASoC: Updates for v5.20 This is a big release thus far and there will probably be more changes to come, it's a combination of a larger than usual crop of new drivers and some subsysetm wide cleanups from Charles rather than anything structural. The SOF and Intel DSP code both also continue to be very actively developed. - Restructing of the set_fmt() callbacks to be specified in terms of the device rather than with semantics depending on if the device is supposed to be a CODEC or SoC, making things clearer in situations like CODEC to CODEC links. - Clean up of the way we flag which DAI naming scheme we use to reflect the progress that's been made modernising things. - Merge of more of the Intel AVS driver stack, including some board integrations. - New version 4 mechanism for communication with SOF DSPs. - Suppoort for dynamically selecting the PLL to use at runtime on i.MX platforms. - Improvements for CODEC to CODEC support in the generic cards. - Support for AMD Jadeite and various machines, Intel MetorLake DSPs, Mediatek MT8186 DSPs and MT6366, nVidia Tegra MDDRC, OPE and PEQ, NXP TFA9890, Qualcomm SDM845, WCD9335 and WAS883x, and Texas Instruments TAS2780.
Diffstat (limited to 'sound/soc/sof/topology.c')
-rw-r--r--sound/soc/sof/topology.c121
1 files changed, 60 insertions, 61 deletions
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index b1fcab7ce48e..9273a70fec25 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -36,9 +36,6 @@
#define TLV_STEP 1
#define TLV_MUTE 2
-/* size of tplg abi in byte */
-#define SOF_TPLG_ABI_SIZE 3
-
/**
* sof_update_ipc_object - Parse multiple sets of tokens within the token array associated with the
* token ID.
@@ -1141,6 +1138,21 @@ static int spcm_bind(struct snd_soc_component *scomp, struct snd_sof_pcm *spcm,
return 0;
}
+static int sof_get_token_value(u32 token_id, struct snd_sof_tuple *tuples, int num_tuples)
+{
+ int i;
+
+ if (!tuples)
+ return -EINVAL;
+
+ for (i = 0; i < num_tuples; i++) {
+ if (tuples[i].token == token_id)
+ return tuples[i].value.v;
+ }
+
+ return -EINVAL;
+}
+
static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_sof_widget *swidget,
struct snd_soc_tplg_dapm_widget *tw,
enum sof_tokens *object_token_list, int count)
@@ -1168,6 +1180,8 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s
/* parse token list for widget */
for (i = 0; i < count; i++) {
+ int num_sets = 1;
+
if (object_token_list[i] >= SOF_TOKEN_COUNT) {
dev_err(scomp->dev, "Invalid token id %d for widget %s\n",
object_token_list[i], swidget->widget->name);
@@ -1175,8 +1189,9 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s
goto err;
}
- /* parse and save UUID in swidget */
- if (object_token_list[i] == SOF_COMP_EXT_TOKENS) {
+ switch (object_token_list[i]) {
+ case SOF_COMP_EXT_TOKENS:
+ /* parse and save UUID in swidget */
ret = sof_parse_tokens(scomp, swidget,
token_list[object_token_list[i]].tokens,
token_list[object_token_list[i]].count,
@@ -1189,11 +1204,41 @@ static int sof_widget_parse_tokens(struct snd_soc_component *scomp, struct snd_s
}
continue;
+ case SOF_IN_AUDIO_FORMAT_TOKENS:
+ case SOF_OUT_AUDIO_FORMAT_TOKENS:
+ case SOF_COPIER_GATEWAY_CFG_TOKENS:
+ case SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS:
+ num_sets = sof_get_token_value(SOF_TKN_COMP_NUM_AUDIO_FORMATS,
+ swidget->tuples, swidget->num_tuples);
+
+ if (num_sets < 0) {
+ dev_err(sdev->dev, "Invalid audio format count for %s\n",
+ swidget->widget->name);
+ ret = num_sets;
+ goto err;
+ }
+
+ if (num_sets > 1) {
+ struct snd_sof_tuple *new_tuples;
+
+ num_tuples += token_list[object_token_list[i]].count * num_sets;
+ new_tuples = krealloc(swidget->tuples,
+ sizeof(*new_tuples) * num_tuples, GFP_KERNEL);
+ if (!new_tuples) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ swidget->tuples = new_tuples;
+ }
+ break;
+ default:
+ break;
}
/* copy one set of tuples per token ID into swidget->tuples */
ret = sof_copy_tuples(sdev, private->array, le32_to_cpu(private->size),
- object_token_list[i], 1, swidget->tuples,
+ object_token_list[i], num_sets, swidget->tuples,
num_tuples, &swidget->num_tuples);
if (ret < 0) {
dev_err(scomp->dev, "Failed parsing %s for widget %s err: %d\n",
@@ -1208,21 +1253,6 @@ err:
return ret;
}
-static int sof_get_token_value(u32 token_id, struct snd_sof_tuple *tuples, int num_tuples)
-{
- int i;
-
- if (!tuples)
- return -EINVAL;
-
- for (i = 0; i < num_tuples; i++) {
- if (tuples[i].token == token_id)
- return tuples[i].value.v;
- }
-
- return -EINVAL;
-}
-
/* external widget init - used for any driver specific init */
static int sof_widget_ready(struct snd_soc_component *scomp, int index,
struct snd_soc_dapm_widget *w,
@@ -1389,7 +1419,6 @@ static int sof_widget_unload(struct snd_soc_component *scomp,
struct soc_bytes_ext *sbe;
struct snd_sof_dai *dai;
struct soc_enum *se;
- int ret = 0;
int i;
swidget = dobj->private;
@@ -1450,7 +1479,7 @@ out:
list_del(&swidget->list);
kfree(swidget);
- return ret;
+ return 0;
}
/*
@@ -1709,6 +1738,10 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_
token_id = SOF_AFE_TOKENS;
num_tuples += token_list[SOF_AFE_TOKENS].count;
break;
+ case SOF_DAI_AMD_DMIC:
+ token_id = SOF_ACPDMIC_TOKENS;
+ num_tuples += token_list[SOF_ACPDMIC_TOKENS].count;
+ break;
default:
break;
}
@@ -1987,45 +2020,11 @@ static int sof_complete(struct snd_soc_component *scomp)
static int sof_manifest(struct snd_soc_component *scomp, int index,
struct snd_soc_tplg_manifest *man)
{
- u32 size;
- u32 abi_version;
-
- size = le32_to_cpu(man->priv.size);
-
- /* backward compatible with tplg without ABI info */
- if (!size) {
- dev_dbg(scomp->dev, "No topology ABI info\n");
- return 0;
- }
-
- if (size != SOF_TPLG_ABI_SIZE) {
- dev_err(scomp->dev, "error: invalid topology ABI size\n");
- return -EINVAL;
- }
-
- dev_info(scomp->dev,
- "Topology: ABI %d:%d:%d Kernel ABI %d:%d:%d\n",
- man->priv.data[0], man->priv.data[1],
- man->priv.data[2], SOF_ABI_MAJOR, SOF_ABI_MINOR,
- SOF_ABI_PATCH);
-
- abi_version = SOF_ABI_VER(man->priv.data[0],
- man->priv.data[1],
- man->priv.data[2]);
-
- if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, abi_version)) {
- dev_err(scomp->dev, "error: incompatible topology ABI version\n");
- return -EINVAL;
- }
+ struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
+ const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg;
- if (SOF_ABI_VERSION_MINOR(abi_version) > SOF_ABI_MINOR) {
- if (!IS_ENABLED(CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS)) {
- dev_warn(scomp->dev, "warn: topology ABI is more recent than kernel\n");
- } else {
- dev_err(scomp->dev, "error: topology ABI is more recent than kernel\n");
- return -EINVAL;
- }
- }
+ if (ipc_tplg_ops->parse_manifest)
+ return ipc_tplg_ops->parse_manifest(scomp, index, man);
return 0;
}