ASoC: SOF: add ipc4 SRC module support
SRC module only needs two parameters : base module config and sink rate. This patch adds prepare and setup for SRC widgets. Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> Signed-off-by: Rander Wang <rander.wang@intel.com> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20220715145216.277003-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
bdb803c828
commit
b85f4fc40d
|
@ -111,6 +111,12 @@ static const struct sof_topology_token gain_tokens[] = {
|
||||||
get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)},
|
get_token_u32, offsetof(struct sof_ipc4_gain_data, init_val)},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* SRC */
|
||||||
|
static const struct sof_topology_token src_tokens[] = {
|
||||||
|
{SOF_TKN_SRC_RATE_OUT, SND_SOC_TPLG_TUPLE_TYPE_WORD, get_token_u32,
|
||||||
|
offsetof(struct sof_ipc4_src, sink_rate)},
|
||||||
|
};
|
||||||
|
|
||||||
static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
|
static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
|
||||||
[SOF_DAI_TOKENS] = {"DAI tokens", dai_tokens, ARRAY_SIZE(dai_tokens)},
|
[SOF_DAI_TOKENS] = {"DAI tokens", dai_tokens, ARRAY_SIZE(dai_tokens)},
|
||||||
[SOF_PIPELINE_TOKENS] = {"Pipeline tokens", pipeline_tokens, ARRAY_SIZE(pipeline_tokens)},
|
[SOF_PIPELINE_TOKENS] = {"Pipeline tokens", pipeline_tokens, ARRAY_SIZE(pipeline_tokens)},
|
||||||
|
@ -134,6 +140,7 @@ static const struct sof_token_info ipc4_token_list[SOF_TOKEN_COUNT] = {
|
||||||
[SOF_AUDIO_FMT_NUM_TOKENS] = {"IPC4 Audio format number tokens",
|
[SOF_AUDIO_FMT_NUM_TOKENS] = {"IPC4 Audio format number tokens",
|
||||||
ipc4_audio_fmt_num_tokens, ARRAY_SIZE(ipc4_audio_fmt_num_tokens)},
|
ipc4_audio_fmt_num_tokens, ARRAY_SIZE(ipc4_audio_fmt_num_tokens)},
|
||||||
[SOF_GAIN_TOKENS] = {"Gain tokens", gain_tokens, ARRAY_SIZE(gain_tokens)},
|
[SOF_GAIN_TOKENS] = {"Gain tokens", gain_tokens, ARRAY_SIZE(gain_tokens)},
|
||||||
|
[SOF_SRC_TOKENS] = {"SRC tokens", src_tokens, ARRAY_SIZE(src_tokens)},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sof_ipc4_dbg_audio_format(struct device *dev,
|
static void sof_ipc4_dbg_audio_format(struct device *dev,
|
||||||
|
@ -740,6 +747,58 @@ err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
|
||||||
|
{
|
||||||
|
struct snd_soc_component *scomp = swidget->scomp;
|
||||||
|
struct sof_ipc4_src *src;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dev_dbg(scomp->dev, "Updating IPC structure for %s\n", swidget->widget->name);
|
||||||
|
|
||||||
|
src = kzalloc(sizeof(*src), GFP_KERNEL);
|
||||||
|
if (!src)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
swidget->private = src;
|
||||||
|
|
||||||
|
/* The out_audio_fmt in topology is ignored as it is not required by SRC */
|
||||||
|
ret = sof_ipc4_get_audio_fmt(scomp, swidget, &src->available_fmt, false);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
ret = sof_update_ipc_object(scomp, src, SOF_SRC_TOKENS, swidget->tuples,
|
||||||
|
swidget->num_tuples, sizeof(src), 1);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(scomp->dev, "Parsing SRC tokens failed\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(scomp->dev, "SRC sink rate %d\n", src->sink_rate);
|
||||||
|
|
||||||
|
ret = sof_ipc4_widget_setup_msg(swidget, &src->msg);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
sof_ipc4_free_audio_fmt(&src->available_fmt);
|
||||||
|
kfree(src);
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!src)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sof_ipc4_free_audio_fmt(&src->available_fmt);
|
||||||
|
kfree(swidget->private);
|
||||||
|
swidget->private = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget)
|
static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget)
|
||||||
{
|
{
|
||||||
struct sof_ipc4_mixer *mixer = swidget->private;
|
struct sof_ipc4_mixer *mixer = swidget->private;
|
||||||
|
@ -1305,6 +1364,37 @@ static int sof_ipc4_prepare_mixer_module(struct snd_sof_widget *swidget,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
|
||||||
|
struct snd_pcm_hw_params *fe_params,
|
||||||
|
struct snd_sof_platform_stream_params *platform_params,
|
||||||
|
struct snd_pcm_hw_params *pipeline_params, int dir)
|
||||||
|
{
|
||||||
|
struct snd_soc_component *scomp = swidget->scomp;
|
||||||
|
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
|
||||||
|
struct sof_ipc4_src *src = swidget->private;
|
||||||
|
struct snd_interval *rate;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
src->available_fmt.ref_audio_fmt = &src->available_fmt.base_config->audio_fmt;
|
||||||
|
|
||||||
|
/* output format is not required to be sent to the FW for SRC */
|
||||||
|
ret = sof_ipc4_init_audio_fmt(sdev, swidget, &src->base_config,
|
||||||
|
NULL, pipeline_params, &src->available_fmt,
|
||||||
|
sizeof(src->base_config));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* update pipeline memory usage */
|
||||||
|
sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &src->base_config);
|
||||||
|
|
||||||
|
/* update pipeline_params for sink widgets */
|
||||||
|
rate = hw_param_interval(pipeline_params, SNDRV_PCM_HW_PARAM_RATE);
|
||||||
|
rate->min = src->sink_rate;
|
||||||
|
rate->max = rate->min;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
|
static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
|
||||||
{
|
{
|
||||||
struct sof_ipc4_control_data *control_data;
|
struct sof_ipc4_control_data *control_data;
|
||||||
|
@ -1360,7 +1450,6 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
|
||||||
u32 ipc_size = 0;
|
u32 ipc_size = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
switch (swidget->id) {
|
switch (swidget->id) {
|
||||||
case snd_soc_dapm_scheduler:
|
case snd_soc_dapm_scheduler:
|
||||||
pipeline = swidget->private;
|
pipeline = swidget->private;
|
||||||
|
@ -1415,6 +1504,16 @@ static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
|
||||||
msg = &mixer->msg;
|
msg = &mixer->msg;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case snd_soc_dapm_src:
|
||||||
|
{
|
||||||
|
struct sof_ipc4_src *src = swidget->private;
|
||||||
|
|
||||||
|
ipc_size = sizeof(struct sof_ipc4_base_module_cfg) + sizeof(src->sink_rate);
|
||||||
|
ipc_data = src;
|
||||||
|
|
||||||
|
msg = &src->msg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
dev_err(sdev->dev, "widget type %d not supported", swidget->id);
|
dev_err(sdev->dev, "widget type %d not supported", swidget->id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1762,6 +1861,15 @@ static enum sof_tokens mixer_token_list[] = {
|
||||||
SOF_COMP_EXT_TOKENS,
|
SOF_COMP_EXT_TOKENS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static enum sof_tokens src_token_list[] = {
|
||||||
|
SOF_COMP_TOKENS,
|
||||||
|
SOF_SRC_TOKENS,
|
||||||
|
SOF_AUDIO_FMT_NUM_TOKENS,
|
||||||
|
SOF_IN_AUDIO_FORMAT_TOKENS,
|
||||||
|
SOF_AUDIO_FORMAT_BUFFER_SIZE_TOKENS,
|
||||||
|
SOF_COMP_EXT_TOKENS,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = {
|
static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TYPE_COUNT] = {
|
||||||
[snd_soc_dapm_aif_in] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm,
|
[snd_soc_dapm_aif_in] = {sof_ipc4_widget_setup_pcm, sof_ipc4_widget_free_comp_pcm,
|
||||||
host_token_list, ARRAY_SIZE(host_token_list), NULL,
|
host_token_list, ARRAY_SIZE(host_token_list), NULL,
|
||||||
|
@ -1790,6 +1898,10 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc4_widget_ops[SND_SOC_DAPM_TY
|
||||||
mixer_token_list, ARRAY_SIZE(mixer_token_list),
|
mixer_token_list, ARRAY_SIZE(mixer_token_list),
|
||||||
NULL, sof_ipc4_prepare_mixer_module,
|
NULL, sof_ipc4_prepare_mixer_module,
|
||||||
NULL},
|
NULL},
|
||||||
|
[snd_soc_dapm_src] = {sof_ipc4_widget_setup_comp_src, sof_ipc4_widget_free_comp_src,
|
||||||
|
src_token_list, ARRAY_SIZE(src_token_list),
|
||||||
|
NULL, sof_ipc4_prepare_src_module,
|
||||||
|
NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct sof_ipc_tplg_ops ipc4_tplg_ops = {
|
const struct sof_ipc_tplg_ops ipc4_tplg_ops = {
|
||||||
|
|
|
@ -242,4 +242,18 @@ struct sof_ipc4_mixer {
|
||||||
struct sof_ipc4_msg msg;
|
struct sof_ipc4_msg msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct sof_ipc4_src SRC config data
|
||||||
|
* @base_config: IPC base config data
|
||||||
|
* @sink_rate: Output rate for sink module
|
||||||
|
* @available_fmt: Available audio format
|
||||||
|
* @msg: IPC4 message struct containing header and data info
|
||||||
|
*/
|
||||||
|
struct sof_ipc4_src {
|
||||||
|
struct sof_ipc4_base_module_cfg base_config;
|
||||||
|
uint32_t sink_rate;
|
||||||
|
struct sof_ipc4_available_audio_format available_fmt;
|
||||||
|
struct sof_ipc4_msg msg;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue