diff mbox series

[2/6] ASoC: SOF: ipc4-topology: add effect widget support

Message ID 20230316151137.7598-3-peter.ujfalusi@linux.intel.com (mailing list archive)
State Accepted
Commit 7711a2bbc8447dd7185c6da9e405d89ce3ec2f0f
Headers show
Series ASoC: SOF: ipc4-topology: Add support for effect widget | expand

Commit Message

Peter Ujfalusi March 16, 2023, 3:11 p.m. UTC
From: Libin Yang <libin.yang@intel.com>

Add the general support of IPC4 effect widgets.

IPC4 effect widgets, known as process modules,  can be EQFIR,
EQIIR, KEYWORD_DETECT, KPB, CHAN_SELECTOR, SMART_AMP and etc.

Signed-off-by: Libin Yang <libin.yang@intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
---
 sound/soc/sof/ipc4-topology.c | 124 ++++++++++++++++++++++++++++++++++
 sound/soc/sof/ipc4-topology.h |  18 +++++
 2 files changed, 142 insertions(+)
diff mbox series

Patch

diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index c00df3956c02..76bd3487bf71 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -793,6 +793,69 @@  static void sof_ipc4_widget_free_comp_mixer(struct snd_sof_widget *swidget)
 	swidget->private = NULL;
 }
 
+/*
+ * Add the process modules support. The process modules are defined as snd_soc_dapm_effect modules.
+ */
+static int sof_ipc4_widget_setup_comp_process(struct snd_sof_widget *swidget)
+{
+	struct snd_soc_component *scomp = swidget->scomp;
+	struct sof_ipc4_process *process;
+	int cfg_size;
+	void *cfg;
+	int ret;
+
+	process = kzalloc(sizeof(*process), GFP_KERNEL);
+	if (!process)
+		return -ENOMEM;
+
+	swidget->private = process;
+
+	ret = sof_ipc4_get_audio_fmt(scomp, swidget, &process->available_fmt,
+				     &process->base_config);
+	if (ret)
+		goto err;
+
+	cfg_size = sizeof(struct sof_ipc4_base_module_cfg);
+
+	cfg = kzalloc(cfg_size, GFP_KERNEL);
+	if (!cfg) {
+		ret = -ENOMEM;
+		goto free_available_fmt;
+	}
+
+	process->ipc_config_data = cfg;
+	process->ipc_config_size = cfg_size;
+	ret = sof_ipc4_widget_setup_msg(swidget, &process->msg);
+	if (ret)
+		goto free_cfg_data;
+
+	sof_ipc4_widget_update_kcontrol_module_id(swidget);
+
+	return 0;
+free_cfg_data:
+	kfree(process->ipc_config_data);
+	process->ipc_config_data = NULL;
+free_available_fmt:
+	sof_ipc4_free_audio_fmt(&process->available_fmt);
+err:
+	kfree(process);
+	swidget->private = NULL;
+	return ret;
+}
+
+static void sof_ipc4_widget_free_comp_process(struct snd_sof_widget *swidget)
+{
+	struct sof_ipc4_process *process = swidget->private;
+
+	if (!process)
+		return;
+
+	kfree(process->ipc_config_data);
+	sof_ipc4_free_audio_fmt(&process->available_fmt);
+	kfree(swidget->private);
+	swidget->private = NULL;
+}
+
 static void
 sof_ipc4_update_pipeline_mem_usage(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget,
 				   struct sof_ipc4_base_module_cfg *base_config)
@@ -1454,6 +1517,38 @@  static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
 	return 0;
 }
 
+static int sof_ipc4_prepare_process_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_process *process = swidget->private;
+	struct sof_ipc4_available_audio_format *available_fmt = &process->available_fmt;
+	void *cfg = process->ipc_config_data;
+	int ret;
+
+	ret = sof_ipc4_init_audio_fmt(sdev, swidget, &process->base_config,
+				      pipeline_params, available_fmt,
+				      available_fmt->input_pin_fmts,
+				      available_fmt->num_input_formats);
+	if (ret < 0)
+		return ret;
+
+	/* update pipeline memory usage */
+	sof_ipc4_update_pipeline_mem_usage(sdev, swidget, &process->base_config);
+
+	/*
+	 * ipc_config_data is composed of the base_config, optional output formats followed
+	 * by the data required for module init in that order.
+	 */
+	memcpy(cfg, &process->base_config, sizeof(struct sof_ipc4_base_module_cfg));
+	cfg += sizeof(struct sof_ipc4_base_module_cfg);
+
+	return 0;
+}
+
 static int sof_ipc4_control_load_volume(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol)
 {
 	struct sof_ipc4_control_data *control_data;
@@ -1652,6 +1747,22 @@  static int sof_ipc4_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget
 		msg = &src->msg;
 		break;
 	}
+	case snd_soc_dapm_effect:
+	{
+		struct sof_ipc4_process *process = swidget->private;
+
+		if (!process->ipc_config_size) {
+			dev_err(sdev->dev, "module %s has no config data!\n",
+				swidget->widget->name);
+			return -EINVAL;
+		}
+
+		ipc_size = process->ipc_config_size;
+		ipc_data = process->ipc_config_data;
+
+		msg = &process->msg;
+		break;
+	}
 	default:
 		dev_err(sdev->dev, "widget type %d not supported", swidget->id);
 		return -EINVAL;
@@ -2257,6 +2368,14 @@  static enum sof_tokens src_token_list[] = {
 	SOF_COMP_EXT_TOKENS,
 };
 
+static enum sof_tokens process_token_list[] = {
+	SOF_COMP_TOKENS,
+	SOF_AUDIO_FMT_NUM_TOKENS,
+	SOF_IN_AUDIO_FORMAT_TOKENS,
+	SOF_OUT_AUDIO_FORMAT_TOKENS,
+	SOF_COMP_EXT_TOKENS,
+};
+
 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,
 				  common_copier_token_list, ARRAY_SIZE(common_copier_token_list),
@@ -2294,6 +2413,11 @@  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_effect] = {sof_ipc4_widget_setup_comp_process,
+				sof_ipc4_widget_free_comp_process,
+				process_token_list, ARRAY_SIZE(process_token_list),
+				NULL, sof_ipc4_prepare_process_module,
+				NULL},
 };
 
 const struct sof_ipc_tplg_ops ipc4_tplg_ops = {
diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h
index fad7a628f782..9fcb978ebc63 100644
--- a/sound/soc/sof/ipc4-topology.h
+++ b/sound/soc/sof/ipc4-topology.h
@@ -347,4 +347,22 @@  struct sof_ipc4_src {
 	struct sof_ipc4_msg msg;
 };
 
+/**
+ * struct sof_ipc4_process - process config data
+ * @base_config: IPC base config data
+ * @output_format: Output audio format
+ * @available_fmt: Available audio format
+ * @ipc_config_data: Process module config data
+ * @ipc_config_size: Size of process module config data
+ * @msg: IPC4 message struct containing header and data info
+ */
+struct sof_ipc4_process {
+	struct sof_ipc4_base_module_cfg base_config;
+	struct sof_ipc4_audio_format output_format;
+	struct sof_ipc4_available_audio_format available_fmt;
+	void *ipc_config_data;
+	uint32_t ipc_config_size;
+	struct sof_ipc4_msg msg;
+};
+
 #endif