summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeppo Ingalsuo <seppo.ingalsuo@linux.intel.com>2025-06-19 13:47:35 +0300
committerMark Brown <broonie@kernel.org>2025-06-20 00:21:17 +0100
commitf9c7c093797fc00c7ce3042387994cf9d6c6d4ce (patch)
tree8203956209def71d3f4d2b89c6040eb48d36e340
parent3d77763c9a6d94ebc258183583891fdf23599a18 (diff)
ASoC: SOF: ipc4-topology: Add load of ASRC component
This patch adds to IPC4 topology parsing the support for the asynchronous sample rate converter (ASRC) SOF component. It is applied for the DAPM widget type SND_SOC_TPLG_DAPM_ASRC. The parsed SOF tokens for ASRC are SOF_TKN_ASRC_RATE_OUT and SOF_TKN_ASRC_OPERATION_MODE. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com> Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com> Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Link: https://patch.msgid.link/20250619104735.26161-1-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/sof/ipc4-topology.c88
-rw-r--r--sound/soc/sof/ipc4-topology.h24
2 files changed, 112 insertions, 0 deletions
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index 540ba140e155..089f2c9fe693 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -145,6 +145,14 @@ static const struct sof_topology_token src_tokens[] = {
offsetof(struct sof_ipc4_src_data, sink_rate)},
};
+/* ASRC */
+static const struct sof_topology_token asrc_tokens[] = {
+ {SOF_TKN_ASRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
+ offsetof(struct sof_ipc4_asrc_data, out_freq)},
+ {SOF_TKN_ASRC_OPERATION_MODE, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
+ offsetof(struct sof_ipc4_asrc_data, asrc_mode)},
+};
+
static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
[SOF_DAI_TOKENS] = {"DAI tokens", dai_tokens, ARRAY_SIZE(dai_tokens)},
[SOF_PIPELINE_TOKENS] = {"Pipeline tokens", pipeline_tokens, ARRAY_SIZE(pipeline_tokens)},
@@ -166,6 +174,7 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
ipc4_audio_fmt_num_tokens, ARRAY_SIZE(ipc4_audio_fmt_num_tokens)},
[SOF_GAIN_TOKENS] = {"Gain tokens", gain_tokens, ARRAY_SIZE(gain_tokens)},
[SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)},
+ [SOF_ASRC_TOKENS] = {"ASRC tokens", asrc_tokens, ARRAY_SIZE(asrc_tokens)},
};
struct snd_sof_widget *sof_ipc4_find_swidget_by_ids(struct snd_sof_dev *sdev,
@@ -1045,6 +1054,50 @@ err:
return ret;
}
+static int sof_ipc4_widget_setup_comp_asrc(struct snd_sof_widget *swidget)
+{
+ struct snd_soc_component *scomp = swidget->scomp;
+ struct snd_sof_pipeline *spipe = swidget->spipe;
+ struct sof_ipc4_asrc *asrc;
+ int ret;
+
+ dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name);
+
+ asrc = kzalloc(sizeof(*asrc), GFP_KERNEL);
+ if (!asrc)
+ return -ENOMEM;
+
+ swidget->private = asrc;
+
+ ret = sof_ipc4_get_audio_fmt(scomp, swidget, &asrc->available_fmt,
+ &asrc->data.base_config);
+ if (ret)
+ goto err;
+
+ ret = sof_update_ipc_object(scomp, &asrc->data, SOF_ASRC_TOKENS, swidget->tuples,
+ swidget->num_tuples, sizeof(*asrc), 1);
+ if (ret) {
+ dev_err(scomp->dev, "Parsing ASRC tokens failed\n");
+ goto err;
+ }
+
+ spipe->core_mask |= BIT(swidget->core);
+
+ dev_dbg(scomp->dev, "ASRC sink rate %d, mode 0x%08x\n",
+ asrc->data.out_freq, asrc->data.asrc_mode);
+
+ ret = sof_ipc4_widget_setup_msg(swidget, &asrc->msg);
+ if (ret)
+ goto err;
+
+ return 0;
+err:
+ sof_ipc4_free_audio_fmt(&asrc->available_fmt);
+ kfree(asrc);
+ swidget->private = NULL;
+ return ret;
+}
+
static void sof_ipc4_widget_free_comp_src(struct snd_sof_widget *swidget)
{
struct sof_ipc4_src *src = swidget->private;
@@ -1057,6 +1110,18 @@ static void sof_ipc4_widget_free_comp_src(struct snd_sof_widget *swidget)
swidget->private = NULL;
}
+static void sof_ipc4_widget_free_comp_asrc(struct snd_sof_widget *swidget)
+{
+ struct sof_ipc4_asrc *asrc = swidget->private;
+
+ if (!asrc)
+ return;
+
+ sof_ipc4_free_audio_fmt(&asrc->available_fmt);
+ kfree(swidget->private);
+ swidget->private = NULL;
+}
+
static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget)
{
struct sof_ipc4_mixer *mixer = swidget->private;
@@ -2817,6 +2882,16 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
msg = &src->msg;
break;
}
+ case snd_soc_dapm_asrc:
+ {
+ struct sof_ipc4_asrc *asrc = swidget->private;
+
+ ipc_size = sizeof(asrc->data);
+ ipc_data = &asrc->data;
+
+ msg = &asrc->msg;
+ break;
+ }
case snd_soc_dapm_effect:
{
struct sof_ipc4_process *process = swidget->private;
@@ -3503,6 +3578,15 @@ static enum sof_tokens src_token_list[] = {
SOF_COMP_EXT_TOKENS,
};
+static enum sof_tokens asrc_token_list[] = {
+ SOF_COMP_TOKENS,
+ SOF_ASRC_TOKENS,
+ SOF_AUDIO_FMT_NUM_TOKENS,
+ SOF_IN_AUDIO_FORMAT_TOKENS,
+ SOF_OUT_AUDIO_FORMAT_TOKENS,
+ SOF_COMP_EXT_TOKENS,
+};
+
static enum sof_tokens process_token_list[] = {
SOF_COMP_TOKENS,
SOF_AUDIO_FMT_NUM_TOKENS,
@@ -3548,6 +3632,10 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TY
src_token_list, ARRAY_SIZE(src_token_list),
NULL, sof_ipc4_prepare_src_module,
NULL},
+ [snd_soc_dapm_asrc] = {sof_ipc4_widget_setup_comp_asrc, sof_ipc4_widget_free_comp_asrc,
+ asrc_token_list, ARRAY_SIZE(asrc_token_list),
+ NULL, sof_ipc4_prepare_src_module, /* Common prepare with SRC */
+ NULL},
[snd_soc_dapm_effect] = {sof_ipc4_widget_setup_comp_process,
sof_ipc4_widget_free_comp_process,
process_token_list, ARRAY_SIZE(process_token_list),
diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h
index f4dc499c0ffe..9e98cac19532 100644
--- a/sound/soc/sof/ipc4-topology.h
+++ b/sound/soc/sof/ipc4-topology.h
@@ -435,6 +435,30 @@ struct sof_ipc4_src {
struct sof_ipc4_msg msg;
};
+/*
+ * struct sof_ipc4_asrc_data - IPC data for ASRC
+ * @base_config: IPC base config data
+ * @out_freq: Output rate for sink module, passed as such from topology to FW.
+ * @asrc_mode: Control for ASRC features with bit-fields, passed as such from topolgy to FW.
+ */
+struct sof_ipc4_asrc_data {
+ struct sof_ipc4_base_module_cfg base_config;
+ uint32_t out_freq;
+ uint32_t asrc_mode;
+} __packed __aligned(4);
+
+/**
+ * struct sof_ipc4_asrc - ASRC config data
+ * @data: IPC base config data
+ * @available_fmt: Available audio format
+ * @msg: IPC4 message struct containing header and data info
+ */
+struct sof_ipc4_asrc {
+ struct sof_ipc4_asrc_data data;
+ struct sof_ipc4_available_audio_format available_fmt;
+ struct sof_ipc4_msg msg;
+};
+
/**
* struct sof_ipc4_base_module_cfg_ext - base module config extension containing the pin format
* information for the module. Both @num_input_pin_fmts and @num_output_pin_fmts cannot be 0 for a