All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4
@ 2022-04-26 17:17 Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 01/11] ASoC: SOF: Add a new op to set up volume table Ranjani Sridharan
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Ranjani Sridharan @ 2022-04-26 17:17 UTC (permalink / raw)
  To: alsa-devel; +Cc: broonie, tiwai, Ranjani Sridharan

This series includes last few remaining miscellaneous patches to prepare
for the introduction of new IPC version, IPC4, in the SOF driver. The changes
include new IPC ops for topology parsing to set up the volume table, prepare
the widgets for set up and free the routes. The remaining patches introduce
new fields in the existing data structures for use in IPC4 and align the flows
for widget/route set up so that they are common for both IPC3 and IPC4.

Ranjani Sridharan (11):
  ASoC: SOF: Add a new op to set up volume table
  ASoC: SOF: sof-audio: reset route status before freeing widget
  ASoC: SOF: sof-audio: Set up widgets from source to sink
  ASoC: SOF: pcm: Move the call to snd_sof_pcm_platform_hw_params()
  ASoC: SOF: expose a couple of functions
  ASoC: SOF: Add a route_free op in struct sof_ipc_tplg_ops
  ASoC: SOF: Add two new fields to struct snd_sof_widget
  ASoC: SOF: pcm: remove unnecessary function declaration
  ASoC: SOF: topology: Skip parsing DAI link tokens if not needed
  ASoC: SOF: clarify use of widget complete flag
  ASoC: SOF: Add a prepare op to IPC topology widget ops

 sound/soc/sof/ipc3-control.c |  38 +++--
 sound/soc/sof/pcm.c          |  23 +--
 sound/soc/sof/sof-audio.c    | 302 +++++++++++++++++++++++++++++------
 sound/soc/sof/sof-audio.h    |  68 +++++++-
 sound/soc/sof/topology.c     |  44 +++--
 5 files changed, 368 insertions(+), 107 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 01/11] ASoC: SOF: Add a new op to set up volume table
  2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
@ 2022-04-26 17:17 ` Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 02/11] ASoC: SOF: sof-audio: reset route status before freeing widget Ranjani Sridharan
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Ranjani Sridharan @ 2022-04-26 17:17 UTC (permalink / raw)
  To: alsa-devel
  Cc: Bard Liao, Pierre-Louis Bossart, tiwai, broonie,
	Ranjani Sridharan, Péter Ujfalusi

Add a new op set_up_volume_table for control IPC ops. Define and set
the op for IPC3.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
---
 sound/soc/sof/ipc3-control.c | 18 ++++++++++++++++++
 sound/soc/sof/sof-audio.h    |  6 ++++++
 sound/soc/sof/topology.c     | 26 +++++++++++---------------
 3 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c
index cde9e481f7f2..bea26e73a741 100644
--- a/sound/soc/sof/ipc3-control.c
+++ b/sound/soc/sof/ipc3-control.c
@@ -694,6 +694,23 @@ static int sof_ipc3_widget_kcontrol_setup(struct snd_sof_dev *sdev,
 	return 0;
 }
 
+static int
+sof_ipc3_set_up_volume_table(struct snd_sof_control *scontrol, int tlv[SOF_TLV_ITEMS], int size)
+{
+	int i;
+
+	/* init the volume table */
+	scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL);
+	if (!scontrol->volume_table)
+		return -ENOMEM;
+
+	/* populate the volume table */
+	for (i = 0; i < size ; i++)
+		scontrol->volume_table[i] = vol_compute_gain(i, tlv);
+
+	return 0;
+}
+
 const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = {
 	.volume_put = sof_ipc3_volume_put,
 	.volume_get = sof_ipc3_volume_get,
@@ -708,4 +725,5 @@ const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = {
 	.bytes_ext_volatile_get = sof_ipc3_bytes_ext_volatile_get,
 	.update = sof_ipc3_control_update,
 	.widget_kcontrol_setup = sof_ipc3_widget_kcontrol_setup,
+	.set_up_volume_table = sof_ipc3_set_up_volume_table,
 };
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index a0af7c421fd9..e254b22ea8a9 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -39,6 +39,8 @@
  */
 #define VOLUME_FWL	16
 
+#define SOF_TLV_ITEMS 3
+
 struct snd_sof_widget;
 struct snd_sof_route;
 struct snd_sof_control;
@@ -88,6 +90,9 @@ struct sof_ipc_tplg_control_ops {
 	void (*update)(struct snd_sof_dev *sdev, void *ipc_control_message);
 	/* Optional callback to setup kcontrols associated with an swidget */
 	int (*widget_kcontrol_setup)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget);
+	/* mandatory callback to set up volume table for volume kcontrols */
+	int (*set_up_volume_table)(struct snd_sof_control *scontrol, int tlv[SOF_TLV_ITEMS],
+				   int size);
 };
 
 /**
@@ -464,4 +469,5 @@ int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum so
 			  size_t object_size, int token_instance_num);
 int sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd,
 				    struct snd_sof_pcm *spcm, int dir);
+u32 vol_compute_gain(u32 value, int *tlv);
 #endif
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 5e959f8c4cb9..739f343010fc 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -32,7 +32,6 @@
 #define VOL_HALF_DB_STEP	50
 
 /* TLV data items */
-#define TLV_ITEMS	3
 #define TLV_MIN		0
 #define TLV_STEP	1
 #define TLV_MUTE	2
@@ -134,7 +133,7 @@ int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum so
 	return 0;
 }
 
-static inline int get_tlv_data(const int *p, int tlv[TLV_ITEMS])
+static inline int get_tlv_data(const int *p, int tlv[SOF_TLV_ITEMS])
 {
 	/* we only support dB scale TLV type at the moment */
 	if ((int)p[SNDRV_CTL_TLVO_TYPE] != SNDRV_CTL_TLVT_DB_SCALE)
@@ -224,7 +223,7 @@ static u32 vol_pow32(u32 a, int exp, u32 fwl)
  * Function to calculate volume gain from TLV data.
  * This function can only handle gain steps that are multiples of 0.5 dB
  */
-static u32 vol_compute_gain(u32 value, int *tlv)
+u32 vol_compute_gain(u32 value, int *tlv)
 {
 	int dB_gain;
 	u32 linear_gain;
@@ -263,20 +262,17 @@ static u32 vol_compute_gain(u32 value, int *tlv)
  * "size" specifies the number of entries in the table
  */
 static int set_up_volume_table(struct snd_sof_control *scontrol,
-			       int tlv[TLV_ITEMS], int size)
+			       int tlv[SOF_TLV_ITEMS], int size)
 {
-	int j;
-
-	/* init the volume table */
-	scontrol->volume_table = kcalloc(size, sizeof(u32), GFP_KERNEL);
-	if (!scontrol->volume_table)
-		return -ENOMEM;
+	struct snd_soc_component *scomp = scontrol->scomp;
+	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
+	const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg;
 
-	/* populate the volume table */
-	for (j = 0; j < size ; j++)
-		scontrol->volume_table[j] = vol_compute_gain(j, tlv);
+	if (tplg_ops->control->set_up_volume_table)
+		return tplg_ops->control->set_up_volume_table(scontrol, tlv, size);
 
-	return 0;
+	dev_err(scomp->dev, "Mandatory op %s not set\n", __func__);
+	return -EINVAL;
 }
 
 struct sof_dai_types {
@@ -772,7 +768,7 @@ static int sof_control_load_volume(struct snd_soc_component *scomp,
 	struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
 	struct snd_soc_tplg_mixer_control *mc =
 		container_of(hdr, struct snd_soc_tplg_mixer_control, hdr);
-	int tlv[TLV_ITEMS];
+	int tlv[SOF_TLV_ITEMS];
 	unsigned int mask;
 	int ret;
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 02/11] ASoC: SOF: sof-audio: reset route status before freeing widget
  2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 01/11] ASoC: SOF: Add a new op to set up volume table Ranjani Sridharan
@ 2022-04-26 17:17 ` Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 03/11] ASoC: SOF: sof-audio: Set up widgets from source to sink Ranjani Sridharan
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Ranjani Sridharan @ 2022-04-26 17:17 UTC (permalink / raw)
  To: alsa-devel
  Cc: Péter Ujfalusi, Pierre-Louis Bossart, tiwai, broonie,
	Ranjani Sridharan, Bard Liao

This is in preparation for IPC4 which requires that the route be reset
before the widget is freed. For IPC3, there is nothing more to be done
other than setting the route status. So it is OK to be moved before the
widget is freed.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/soc/sof/sof-audio.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index e2ec60887568..1180d6bab33e 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -34,6 +34,9 @@ int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
 	if (--swidget->use_count)
 		return 0;
 
+	/* reset route setup status for all routes that contain this widget */
+	sof_reset_route_setup_status(sdev, swidget);
+
 	/* continue to disable core even if IPC fails */
 	if (tplg_ops->widget_free)
 		err = tplg_ops->widget_free(sdev, swidget);
@@ -50,8 +53,6 @@ int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
 			err = ret;
 	}
 
-	/* reset route setup status for all routes that contain this widget */
-	sof_reset_route_setup_status(sdev, swidget);
 	swidget->complete = 0;
 
 	/*
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 03/11] ASoC: SOF: sof-audio: Set up widgets from source to sink
  2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 01/11] ASoC: SOF: Add a new op to set up volume table Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 02/11] ASoC: SOF: sof-audio: reset route status before freeing widget Ranjani Sridharan
@ 2022-04-26 17:17 ` Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 04/11] ASoC: SOF: pcm: Move the call to snd_sof_pcm_platform_hw_params() Ranjani Sridharan
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Ranjani Sridharan @ 2022-04-26 17:17 UTC (permalink / raw)
  To: alsa-devel
  Cc: Kai Vehmanen, Bard Liao, Pierre-Louis Bossart, tiwai, broonie,
	Ranjani Sridharan, Péter Ujfalusi

For IPC3, the order of setting up the widgets associated with a PCM
doesn't matter. But for IPC4, widgets must be set up from the source to
the sink in order. In order to accommodate this, change the
sof_widget_list_setup/free() functions to set up/free widgets starting
with the source widget all the way to the sink widget for all pipelines.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
---
 sound/soc/sof/sof-audio.c | 170 +++++++++++++++++++++++++++-----------
 sound/soc/sof/sof-audio.h |   7 ++
 2 files changed, 130 insertions(+), 47 deletions(-)

diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index 1180d6bab33e..0bc6c3ef0cd4 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -253,29 +253,135 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev,
 	return 0;
 }
 
+/*
+ * free all widgets in the sink path starting from the source widget
+ * (DAI type for capture, AIF type for playback)
+ */
+static int sof_free_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget,
+				    int dir)
+{
+	struct snd_soc_dapm_path *p;
+	int err;
+	int ret = 0;
+
+	/* free all widgets even in case of error to keep use counts balanced */
+	snd_soc_dapm_widget_for_each_sink_path(widget, p) {
+		if (!p->walking && p->sink->dobj.private && widget->dobj.private) {
+			p->walking = true;
+			if (WIDGET_IS_AIF_OR_DAI(widget->id)) {
+				err = sof_widget_free(sdev, widget->dobj.private);
+				if (err < 0)
+					ret = err;
+			}
+
+			err = sof_widget_free(sdev, p->sink->dobj.private);
+			if (err < 0)
+				ret = err;
+
+			err = sof_free_widgets_in_path(sdev, p->sink, dir);
+			if (err < 0)
+				ret = err;
+			p->walking = false;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * set up all widgets in the sink path starting from the source widget
+ * (DAI type for capture, AIF type for playback).
+ * The error path in this function ensures that all successfully set up widgets getting freed.
+ */
+static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget,
+				      int dir)
+{
+	struct snd_soc_dapm_path *p;
+	int ret;
+
+	snd_soc_dapm_widget_for_each_sink_path(widget, p) {
+		if (!p->walking && p->sink->dobj.private && widget->dobj.private) {
+			p->walking = true;
+			if (WIDGET_IS_AIF_OR_DAI(widget->id)) {
+				ret = sof_widget_setup(sdev, widget->dobj.private);
+				if (ret < 0)
+					goto out;
+			}
+
+			ret = sof_widget_setup(sdev, p->sink->dobj.private);
+			if (ret < 0) {
+				if (WIDGET_IS_AIF_OR_DAI(widget->id))
+					sof_widget_free(sdev, widget->dobj.private);
+				goto out;
+			}
+
+			ret = sof_set_up_widgets_in_path(sdev, p->sink, dir);
+			if (ret < 0) {
+				if (WIDGET_IS_AIF_OR_DAI(widget->id))
+					sof_widget_free(sdev, widget->dobj.private);
+				sof_widget_free(sdev, p->sink->dobj.private);
+			}
+out:
+			p->walking = false;
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int
+sof_setup_or_free_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_list *list,
+				   bool dir, enum sof_widget_op op)
+{
+	struct snd_soc_dapm_widget *widget;
+	int ret, i;
+
+	for_each_dapm_widgets(list, i, widget) {
+		/* starting widget for playback is AIF type */
+		if (dir == SNDRV_PCM_STREAM_PLAYBACK && !WIDGET_IS_AIF(widget->id))
+			continue;
+
+		/* starting widget for capture is DAI type */
+		if (dir == SNDRV_PCM_STREAM_CAPTURE && !WIDGET_IS_DAI(widget->id))
+			continue;
+
+		switch (op) {
+		case SOF_WIDGET_SETUP:
+			ret = sof_set_up_widgets_in_path(sdev, widget, dir);
+			break;
+		case SOF_WIDGET_FREE:
+			ret = sof_free_widgets_in_path(sdev, widget, dir);
+			break;
+		default:
+			dev_err(sdev->dev, "Invalid widget op %d\n", op);
+			return -EINVAL;
+		}
+		if (ret < 0) {
+			dev_err(sdev->dev, "Failed to %s connected widgets\n",
+				op == SOF_WIDGET_SETUP ? "set up" : "free");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir)
 {
 	const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg;
 	struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
 	struct snd_soc_dapm_widget *widget;
-	int i, ret, num_widgets;
+	int i, ret;
 
 	/* nothing to set up */
 	if (!list)
 		return 0;
 
-	/* set up widgets in the list */
-	for_each_dapm_widgets(list, num_widgets, widget) {
-		struct snd_sof_widget *swidget = widget->dobj.private;
-
-		if (!swidget)
-			continue;
-
-		/* set up the widget */
-		ret = sof_widget_setup(sdev, swidget);
-		if (ret < 0)
-			goto widget_free;
-	}
+	ret = sof_setup_or_free_widgets_in_order(sdev, list, dir, SOF_WIDGET_SETUP);
+	if (ret < 0)
+		return ret;
 
 	/*
 	 * error in setting pipeline connections will result in route status being reset for
@@ -316,18 +422,7 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, in
 	return 0;
 
 widget_free:
-	/* free all widgets that have been set up successfully */
-	for_each_dapm_widgets(list, i, widget) {
-		struct snd_sof_widget *swidget = widget->dobj.private;
-
-		if (!swidget)
-			continue;
-
-		if (!num_widgets--)
-			break;
-
-		sof_widget_free(sdev, swidget);
-	}
+	sof_setup_or_free_widgets_in_order(sdev, list, dir, SOF_WIDGET_FREE);
 
 	return ret;
 }
@@ -335,37 +430,18 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, in
 int sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir)
 {
 	struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
-	struct snd_soc_dapm_widget *widget;
-	int i, ret;
-	int ret1 = 0;
+	int ret;
 
 	/* nothing to free */
 	if (!list)
 		return 0;
 
-	/*
-	 * Free widgets in the list. This can fail but continue freeing other widgets to keep
-	 * use_counts balanced.
-	 */
-	for_each_dapm_widgets(list, i, widget) {
-		struct snd_sof_widget *swidget = widget->dobj.private;
-
-		if (!swidget)
-			continue;
-
-		/*
-		 * free widget and its pipe_widget. Either of these can fail, but free as many as
-		 * possible before freeing the list and returning the error.
-		 */
-		ret = sof_widget_free(sdev, swidget);
-		if (ret < 0)
-			ret1 = ret;
-	}
+	ret = sof_setup_or_free_widgets_in_order(sdev, list, dir, SOF_WIDGET_FREE);
 
 	snd_soc_dapm_dai_free_widgets(&list);
 	spcm->stream[dir].list = NULL;
 
-	return ret1;
+	return ret;
 }
 
 /*
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index e254b22ea8a9..eb882ed7d0e4 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -29,10 +29,17 @@
 #define DMA_CHAN_INVALID	0xFFFFFFFF
 
 #define WIDGET_IS_DAI(id) ((id) == snd_soc_dapm_dai_in || (id) == snd_soc_dapm_dai_out)
+#define WIDGET_IS_AIF(id) ((id) == snd_soc_dapm_aif_in || (id) == snd_soc_dapm_aif_out)
+#define WIDGET_IS_AIF_OR_DAI(id) (WIDGET_IS_DAI(id) || WIDGET_IS_AIF(id))
 
 #define SOF_DAI_CLK_INTEL_SSP_MCLK	0
 #define SOF_DAI_CLK_INTEL_SSP_BCLK	1
 
+enum sof_widget_op {
+	SOF_WIDGET_FREE,
+	SOF_WIDGET_SETUP,
+};
+
 /*
  * Volume fractional word length define to 16 sets
  * the volume linear gain value to use Qx.16 format
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 04/11] ASoC: SOF: pcm: Move the call to snd_sof_pcm_platform_hw_params()
  2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
                   ` (2 preceding siblings ...)
  2022-04-26 17:17 ` [PATCH 03/11] ASoC: SOF: sof-audio: Set up widgets from source to sink Ranjani Sridharan
@ 2022-04-26 17:17 ` Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 05/11] ASoC: SOF: expose a couple of functions Ranjani Sridharan
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Ranjani Sridharan @ 2022-04-26 17:17 UTC (permalink / raw)
  To: alsa-devel
  Cc: Bard Liao, Pierre-Louis Bossart, tiwai, broonie,
	Ranjani Sridharan, Péter Ujfalusi

IPC4 requires the platform_params be passed when invoking
sof_pcm_setup_connected_widgets(). So move the call to
snd_sof_pcm_platform_hw_params() before calling
sof_pcm_setup_connected_widgets(). This has no functional impact.

sof_pcm_setup_connected_widgets will be modified in the follow up
patches to accept the platform params as an argument.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
---
 sound/soc/sof/pcm.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
index 6242327e663e..2d21e531ac4f 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -150,6 +150,12 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
 	dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n",
 		spcm->pcm.pcm_id, substream->stream);
 
+	ret = snd_sof_pcm_platform_hw_params(sdev, substream, params, &platform_params);
+	if (ret < 0) {
+		dev_err(component->dev, "platform hw params failed\n");
+		return ret;
+	}
+
 	/* if this is a repeated hw_params without hw_free, skip setting up widgets */
 	if (!spcm->stream[substream->stream].list) {
 		ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, substream->stream);
@@ -166,12 +172,6 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
 			return ret;
 	}
 
-	ret = snd_sof_pcm_platform_hw_params(sdev, substream, params, &platform_params);
-	if (ret < 0) {
-		dev_err(component->dev, "platform hw params failed\n");
-		return ret;
-	}
-
 	if (pcm_ops->hw_params) {
 		ret = pcm_ops->hw_params(component, substream, params, &platform_params);
 		if (ret < 0)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 05/11] ASoC: SOF: expose a couple of functions
  2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
                   ` (3 preceding siblings ...)
  2022-04-26 17:17 ` [PATCH 04/11] ASoC: SOF: pcm: Move the call to snd_sof_pcm_platform_hw_params() Ranjani Sridharan
@ 2022-04-26 17:17 ` Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 06/11] ASoC: SOF: Add a route_free op in struct sof_ipc_tplg_ops Ranjani Sridharan
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Ranjani Sridharan @ 2022-04-26 17:17 UTC (permalink / raw)
  To: alsa-devel
  Cc: Bard Liao, Pierre-Louis Bossart, tiwai, broonie,
	Ranjani Sridharan, Péter Ujfalusi

Expose the mixer_to_ipc() and ipc_to_mixer() functions for reuse in
IPC4.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
---
 sound/soc/sof/ipc3-control.c | 20 --------------------
 sound/soc/sof/sof-audio.h    | 20 ++++++++++++++++++++
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c
index bea26e73a741..4347adcc6543 100644
--- a/sound/soc/sof/ipc3-control.c
+++ b/sound/soc/sof/ipc3-control.c
@@ -90,26 +90,6 @@ static int sof_ipc3_set_get_kcontrol_data(struct snd_sof_control *scontrol, bool
 	return iops->set_get_data(sdev, cdata, cdata->rhdr.hdr.size, set);
 }
 
-static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size)
-{
-	if (value >= size)
-		return volume_map[size - 1];
-
-	return volume_map[value];
-}
-
-static inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size)
-{
-	int i;
-
-	for (i = 0; i < size; i++) {
-		if (volume_map[i] >= value)
-			return i;
-	}
-
-	return i - 1;
-}
-
 static void snd_sof_refresh_control(struct snd_sof_control *scontrol)
 {
 	struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index eb882ed7d0e4..e3cfc813975b 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -48,6 +48,26 @@ enum sof_widget_op {
 
 #define SOF_TLV_ITEMS 3
 
+static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size)
+{
+	if (value >= size)
+		return volume_map[size - 1];
+
+	return volume_map[value];
+}
+
+static inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++) {
+		if (volume_map[i] >= value)
+			return i;
+	}
+
+	return i - 1;
+}
+
 struct snd_sof_widget;
 struct snd_sof_route;
 struct snd_sof_control;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 06/11] ASoC: SOF: Add a route_free op in struct sof_ipc_tplg_ops
  2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
                   ` (4 preceding siblings ...)
  2022-04-26 17:17 ` [PATCH 05/11] ASoC: SOF: expose a couple of functions Ranjani Sridharan
@ 2022-04-26 17:17 ` Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 07/11] ASoC: SOF: Add two new fields to struct snd_sof_widget Ranjani Sridharan
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Ranjani Sridharan @ 2022-04-26 17:17 UTC (permalink / raw)
  To: alsa-devel
  Cc: Bard Liao, Pierre-Louis Bossart, tiwai, broonie,
	Ranjani Sridharan, Péter Ujfalusi

IPC4 requires that the widgets be unbound in the firmware before they
are freed. So add a new op in struct sof_ipc_tplg_ops that will be used
to send the IPC to the firmware to unbind widgets.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
---
 sound/soc/sof/sof-audio.c | 7 ++++++-
 sound/soc/sof/sof-audio.h | 2 ++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index 0bc6c3ef0cd4..07576ed3c4fa 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -14,11 +14,16 @@
 
 static void sof_reset_route_setup_status(struct snd_sof_dev *sdev, struct snd_sof_widget *widget)
 {
+	const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg;
 	struct snd_sof_route *sroute;
 
 	list_for_each_entry(sroute, &sdev->route_list, list)
-		if (sroute->src_widget == widget || sroute->sink_widget == widget)
+		if (sroute->src_widget == widget || sroute->sink_widget == widget) {
+			if (sroute->setup && tplg_ops->route_free)
+				tplg_ops->route_free(sdev, sroute);
+
 			sroute->setup = false;
+		}
 }
 
 int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index e3cfc813975b..7ca87056b106 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -146,6 +146,7 @@ struct sof_ipc_tplg_widget_ops {
  *	    initialized to 0.
  * @control: Pointer to the IPC-specific ops for topology kcontrol IO
  * @route_setup: Function pointer for setting up pipeline connections
+ * @route_free: Optional op for freeing pipeline connections.
  * @token_list: List of all tokens supported by the IPC version. The size of the token_list
  *		array should be SOF_TOKEN_COUNT. The unused elements in the array will be
  *		initialized to 0.
@@ -163,6 +164,7 @@ struct sof_ipc_tplg_ops {
 	const struct sof_ipc_tplg_widget_ops *widget;
 	const struct sof_ipc_tplg_control_ops *control;
 	int (*route_setup)(struct snd_sof_dev *sdev, struct snd_sof_route *sroute);
+	int (*route_free)(struct snd_sof_dev *sdev, struct snd_sof_route *sroute);
 	const struct sof_token_info *token_list;
 	int (*control_setup)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol);
 	int (*control_free)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 07/11] ASoC: SOF: Add two new fields to struct snd_sof_widget
  2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
                   ` (5 preceding siblings ...)
  2022-04-26 17:17 ` [PATCH 06/11] ASoC: SOF: Add a route_free op in struct sof_ipc_tplg_ops Ranjani Sridharan
@ 2022-04-26 17:17 ` Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 08/11] ASoC: SOF: pcm: remove unnecessary function declaration Ranjani Sridharan
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Ranjani Sridharan @ 2022-04-26 17:17 UTC (permalink / raw)
  To: alsa-devel
  Cc: Bard Liao, Pierre-Louis Bossart, tiwai, broonie,
	Ranjani Sridharan, Péter Ujfalusi

Add two new fields, instance_id and module_info to struct
snd_sof_widget. instance_id for widgets will be assigned when they are
set up in the DSP and reset when the widgets are freed. module_info is
used to save information the firmware provides about each module in its
manifest.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
---
 sound/soc/sof/sof-audio.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index 7ca87056b106..4deab3ded8a5 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -330,7 +330,12 @@ struct snd_sof_widget {
 	int complete;
 	int use_count; /* use_count will be protected by the PCM mutex held by the core */
 	int core;
-	int id;
+	int id; /* id is the DAPM widget type */
+	/*
+	 * Instance ID is set dynamically when the widget gets set up in the FW. It should be
+	 * unique for each module type across all pipelines. This will not be used in SOF_IPC.
+	 */
+	int instance_id;
 
 	/*
 	 * Flag indicating if the widget should be set up dynamically when a PCM is opened.
@@ -345,6 +350,7 @@ struct snd_sof_widget {
 	struct snd_soc_dapm_widget *widget;
 	struct list_head list;	/* list in sdev widget list */
 	struct snd_sof_widget *pipe_widget;
+	void *module_info;
 
 	const guid_t uuid;
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 08/11] ASoC: SOF: pcm: remove unnecessary function declaration
  2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
                   ` (6 preceding siblings ...)
  2022-04-26 17:17 ` [PATCH 07/11] ASoC: SOF: Add two new fields to struct snd_sof_widget Ranjani Sridharan
@ 2022-04-26 17:17 ` Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 09/11] ASoC: SOF: topology: Skip parsing DAI link tokens if not needed Ranjani Sridharan
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Ranjani Sridharan @ 2022-04-26 17:17 UTC (permalink / raw)
  To: alsa-devel
  Cc: Bard Liao, Pierre-Louis Bossart, tiwai, broonie,
	Ranjani Sridharan, Péter Ujfalusi

sof_pcm_setup_connected_widgets() can be a static function in pcm.c. No
need to declare it in the header.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
---
 sound/soc/sof/pcm.c       | 5 +++--
 sound/soc/sof/sof-audio.h | 2 --
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
index 2d21e531ac4f..095ca0d9d5ae 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -82,8 +82,9 @@ void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream)
 }
 EXPORT_SYMBOL(snd_sof_pcm_period_elapsed);
 
-int sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd,
-				    struct snd_sof_pcm *spcm, int dir)
+static int
+sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd,
+				struct snd_sof_pcm *spcm, int dir)
 {
 	struct snd_soc_dai *dai;
 	int ret, j;
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index 4deab3ded8a5..5967d034188a 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -502,7 +502,5 @@ int get_token_uuid(void *elem, void *object, u32 offset);
 int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum sof_tokens token_id,
 			  struct snd_sof_tuple *tuples, int num_tuples,
 			  size_t object_size, int token_instance_num);
-int sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd,
-				    struct snd_sof_pcm *spcm, int dir);
 u32 vol_compute_gain(u32 value, int *tlv);
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 09/11] ASoC: SOF: topology: Skip parsing DAI link tokens if not needed
  2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
                   ` (7 preceding siblings ...)
  2022-04-26 17:17 ` [PATCH 08/11] ASoC: SOF: pcm: remove unnecessary function declaration Ranjani Sridharan
@ 2022-04-26 17:17 ` Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 10/11] ASoC: SOF: clarify use of widget complete flag Ranjani Sridharan
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Ranjani Sridharan @ 2022-04-26 17:17 UTC (permalink / raw)
  To: alsa-devel
  Cc: Bard Liao, Pierre-Louis Bossart, tiwai, broonie,
	Ranjani Sridharan, Péter Ujfalusi

Do not parse these tokens if they are not defined in the IPC version
specific token list. In the case of IPC4 with HDA topologies for
example, no DAI link specific tokens need to be added in topology.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
---
 sound/soc/sof/topology.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 739f343010fc..b1fcab7ce48e 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -1721,14 +1721,16 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_
 		return -ENOMEM;
 	}
 
-	/* parse one set of DAI link tokens */
-	ret = sof_copy_tuples(sdev, private->array, le32_to_cpu(private->size),
-			      SOF_DAI_LINK_TOKENS, 1, slink->tuples,
-			      num_tuples, &slink->num_tuples);
-	if (ret < 0) {
-		dev_err(scomp->dev, "failed to parse %s for dai link %s\n",
-			token_list[SOF_DAI_LINK_TOKENS].name, link->name);
-		goto err;
+	if (token_list[SOF_DAI_LINK_TOKENS].tokens) {
+		/* parse one set of DAI link tokens */
+		ret = sof_copy_tuples(sdev, private->array, le32_to_cpu(private->size),
+				      SOF_DAI_LINK_TOKENS, 1, slink->tuples,
+				      num_tuples, &slink->num_tuples);
+		if (ret < 0) {
+			dev_err(scomp->dev, "failed to parse %s for dai link %s\n",
+				token_list[SOF_DAI_LINK_TOKENS].name, link->name);
+			goto err;
+		}
 	}
 
 	/* nothing more to do if there are no DAI type-specific tokens defined */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 10/11] ASoC: SOF: clarify use of widget complete flag
  2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
                   ` (8 preceding siblings ...)
  2022-04-26 17:17 ` [PATCH 09/11] ASoC: SOF: topology: Skip parsing DAI link tokens if not needed Ranjani Sridharan
@ 2022-04-26 17:17 ` Ranjani Sridharan
  2022-04-26 17:17 ` [PATCH 11/11] ASoC: SOF: Add a prepare op to IPC topology widget ops Ranjani Sridharan
  2022-05-03 15:50 ` [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Mark Brown
  11 siblings, 0 replies; 13+ messages in thread
From: Ranjani Sridharan @ 2022-04-26 17:17 UTC (permalink / raw)
  To: alsa-devel
  Cc: Bard Liao, Pierre-Louis Bossart, tiwai, broonie,
	Ranjani Sridharan, Péter Ujfalusi

Currently, the complete flag is used only for the snd_soc_dapm_scheduler
type widgets to indicate that the pipeline has been set up. All other
widgets do not need it. Add a comment to clarify its usage and set the
complete flag to false only for the scheduler widget in
sof_widget_free().

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 sound/soc/sof/sof-audio.c | 3 +--
 sound/soc/sof/sof-audio.h | 4 ++++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index 07576ed3c4fa..f7c9e5db3d9e 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -58,8 +58,6 @@ int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
 			err = ret;
 	}
 
-	swidget->complete = 0;
-
 	/*
 	 * free the scheduler widget (same as pipe_widget) associated with the current swidget.
 	 * skip for static pipelines
@@ -68,6 +66,7 @@ int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget)
 		ret = sof_widget_free(sdev, swidget->pipe_widget);
 		if (ret < 0 && !err)
 			err = ret;
+		swidget->pipe_widget->complete = 0;
 	}
 
 	if (!err)
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index 5967d034188a..2db4eb5edcf5 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -327,6 +327,10 @@ struct snd_sof_widget {
 	struct snd_soc_component *scomp;
 	int comp_id;
 	int pipeline_id;
+	/*
+	 * complete flag is used to indicate that pipeline set up is complete for scheduler type
+	 * widgets. It is unused for all other widget types.
+	 */
 	int complete;
 	int use_count; /* use_count will be protected by the PCM mutex held by the core */
 	int core;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 11/11] ASoC: SOF: Add a prepare op to IPC topology widget ops
  2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
                   ` (9 preceding siblings ...)
  2022-04-26 17:17 ` [PATCH 10/11] ASoC: SOF: clarify use of widget complete flag Ranjani Sridharan
@ 2022-04-26 17:17 ` Ranjani Sridharan
  2022-05-03 15:50 ` [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Mark Brown
  11 siblings, 0 replies; 13+ messages in thread
From: Ranjani Sridharan @ 2022-04-26 17:17 UTC (permalink / raw)
  To: alsa-devel
  Cc: Bard Liao, Pierre-Louis Bossart, tiwai, broonie,
	Ranjani Sridharan, Péter Ujfalusi

In order to set up a pipeline with IPC4, the total memory usage for the
pipeline needs to be calculated based on the list of connected widgets.
Add a new ipc_prepare() op to struct sof_ipc_tplg_widget_ops that will be
used to calculate the memory usage for each widget in the pipelines
associated with a PCM and prepare the widget for getting set up in the
DSP. The prepare step will be used to allocate memory for the IPC
payload, assign instance ID and update the config data for the widget
based on the runtime PCM params. Once prepared, the setup step is used
to send the IPC to create the widget in the DSP.

Add an ipc_unprepare() op to unprepare the widget i.e free the memory
allocated during prepare, free the instance ID etc. This should be
invoked after the widget is freed.

A new flag "prepared" is added to struct snd_sof_widget to track the
prepared status of widgets.

Also, IPC4 requires the platform_params and the runtime PCM params in
order to prepare a widget for set up. So modify the signature of
sof_pcm_setup_connected_widgets() and sof_widget_list_setup() to accept
these as arguments.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 sound/soc/sof/pcm.c       |   8 ++-
 sound/soc/sof/sof-audio.c | 139 +++++++++++++++++++++++++++++++++++---
 sound/soc/sof/sof-audio.h |  21 +++++-
 3 files changed, 154 insertions(+), 14 deletions(-)

diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
index 095ca0d9d5ae..a76d0b5b2ad9 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -84,7 +84,8 @@ EXPORT_SYMBOL(snd_sof_pcm_period_elapsed);
 
 static int
 sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd,
-				struct snd_sof_pcm *spcm, int dir)
+				struct snd_sof_pcm *spcm, struct snd_pcm_hw_params *params,
+				struct snd_sof_platform_stream_params *platform_params, int dir)
 {
 	struct snd_soc_dai *dai;
 	int ret, j;
@@ -103,7 +104,7 @@ sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_run
 
 		spcm->stream[dir].list = list;
 
-		ret = sof_widget_list_setup(sdev, spcm, dir);
+		ret = sof_widget_list_setup(sdev, spcm, params, platform_params, dir);
 		if (ret < 0) {
 			dev_err(sdev->dev, "error: failed widget list set up for pcm %d dir %d\n",
 				spcm->pcm.pcm_id, dir);
@@ -159,7 +160,8 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
 
 	/* if this is a repeated hw_params without hw_free, skip setting up widgets */
 	if (!spcm->stream[substream->stream].list) {
-		ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, substream->stream);
+		ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, params, &platform_params,
+						      substream->stream);
 		if (ret < 0)
 			return ret;
 	}
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index f7c9e5db3d9e..26a62b3b3c37 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -257,6 +257,79 @@ static int sof_setup_pipeline_connections(struct snd_sof_dev *sdev,
 	return 0;
 }
 
+static void
+sof_unprepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget)
+{
+	const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg;
+	const struct sof_ipc_tplg_widget_ops *widget_ops = ipc_tplg_ops->widget;
+	struct snd_sof_widget *swidget = widget->dobj.private;
+	struct snd_soc_dapm_path *p;
+
+	if (!widget_ops[widget->id].ipc_unprepare || !swidget->prepared)
+		goto sink_unprepare;
+
+	/* unprepare the source widget */
+	widget_ops[widget->id].ipc_unprepare(swidget);
+	swidget->prepared = false;
+
+sink_unprepare:
+	/* unprepare all widgets in the sink paths */
+	snd_soc_dapm_widget_for_each_sink_path(widget, p) {
+		if (!p->walking && p->sink->dobj.private) {
+			p->walking = true;
+			sof_unprepare_widgets_in_path(sdev, p->sink);
+			p->walking = false;
+		}
+	}
+}
+
+static int
+sof_prepare_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *widget,
+			    struct snd_pcm_hw_params *fe_params,
+			    struct snd_sof_platform_stream_params *platform_params,
+			    struct snd_pcm_hw_params *pipeline_params, int dir)
+{
+	const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg;
+	const struct sof_ipc_tplg_widget_ops *widget_ops = ipc_tplg_ops->widget;
+	struct snd_sof_widget *swidget = widget->dobj.private;
+	struct snd_soc_dapm_path *p;
+	int ret;
+
+	if (!widget_ops[widget->id].ipc_prepare || swidget->prepared)
+		goto sink_prepare;
+
+	/* prepare the source widget */
+	ret = widget_ops[widget->id].ipc_prepare(swidget, fe_params, platform_params,
+					     pipeline_params, dir);
+	if (ret < 0) {
+		dev_err(sdev->dev, "failed to prepare widget %s\n", widget->name);
+		return ret;
+	}
+
+	swidget->prepared = true;
+
+sink_prepare:
+	/* prepare all widgets in the sink paths */
+	snd_soc_dapm_widget_for_each_sink_path(widget, p) {
+		if (!p->walking && p->sink->dobj.private) {
+			p->walking = true;
+			ret = sof_prepare_widgets_in_path(sdev, p->sink,  fe_params,
+							  platform_params, pipeline_params, dir);
+			p->walking = false;
+			if (ret < 0) {
+				/* unprepare the source widget */
+				if (!widget_ops[widget->id].ipc_unprepare && swidget->prepared) {
+					widget_ops[widget->id].ipc_unprepare(swidget);
+					swidget->prepared = false;
+				}
+				return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
 /*
  * free all widgets in the sink path starting from the source widget
  * (DAI type for capture, AIF type for playback)
@@ -336,11 +409,15 @@ static int sof_set_up_widgets_in_path(struct snd_sof_dev *sdev, struct snd_soc_d
 }
 
 static int
-sof_setup_or_free_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_list *list,
-				   bool dir, enum sof_widget_op op)
+sof_walk_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget_list *list,
+			  struct snd_pcm_hw_params *fe_params,
+			  struct snd_sof_platform_stream_params *platform_params, int dir,
+			  enum sof_widget_op op)
 {
 	struct snd_soc_dapm_widget *widget;
-	int ret, i;
+	char *str;
+	int ret = 0;
+	int i;
 
 	for_each_dapm_widgets(list, i, widget) {
 		/* starting widget for playback is AIF type */
@@ -354,17 +431,38 @@ sof_setup_or_free_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm
 		switch (op) {
 		case SOF_WIDGET_SETUP:
 			ret = sof_set_up_widgets_in_path(sdev, widget, dir);
+			str = "set up";
 			break;
 		case SOF_WIDGET_FREE:
 			ret = sof_free_widgets_in_path(sdev, widget, dir);
+			str = "free";
+			break;
+		case SOF_WIDGET_PREPARE:
+		{
+			struct snd_pcm_hw_params pipeline_params;
+
+			str = "prepare";
+			/*
+			 * When walking the list of connected widgets, the pipeline_params for each
+			 * widget is modified by the source widget in the path. Use a local
+			 * copy of the runtime params as the pipeline_params so that the runtime
+			 * params does not get overwritten.
+			 */
+			memcpy(&pipeline_params, fe_params, sizeof(*fe_params));
+
+			ret = sof_prepare_widgets_in_path(sdev, widget, fe_params,
+							  platform_params, &pipeline_params, dir);
+			break;
+		}
+		case SOF_WIDGET_UNPREPARE:
+			sof_unprepare_widgets_in_path(sdev, widget);
 			break;
 		default:
 			dev_err(sdev->dev, "Invalid widget op %d\n", op);
 			return -EINVAL;
 		}
 		if (ret < 0) {
-			dev_err(sdev->dev, "Failed to %s connected widgets\n",
-				op == SOF_WIDGET_SETUP ? "set up" : "free");
+			dev_err(sdev->dev, "Failed to %s connected widgets\n", str);
 			return ret;
 		}
 	}
@@ -372,7 +470,10 @@ sof_setup_or_free_widgets_in_order(struct snd_sof_dev *sdev, struct snd_soc_dapm
 	return 0;
 }
 
-int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir)
+int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
+			  struct snd_pcm_hw_params *fe_params,
+			  struct snd_sof_platform_stream_params *platform_params,
+			  int dir)
 {
 	const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg;
 	struct snd_soc_dapm_widget_list *list = spcm->stream[dir].list;
@@ -383,10 +484,24 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, in
 	if (!list)
 		return 0;
 
-	ret = sof_setup_or_free_widgets_in_order(sdev, list, dir, SOF_WIDGET_SETUP);
+	/*
+	 * Prepare widgets for set up. The prepare step is used to allocate memory, assign
+	 * instance ID and pick the widget configuration based on the runtime PCM params.
+	 */
+	ret = sof_walk_widgets_in_order(sdev, list, fe_params, platform_params,
+					dir, SOF_WIDGET_PREPARE);
 	if (ret < 0)
 		return ret;
 
+	/* Set up is used to send the IPC to the DSP to create the widget */
+	ret = sof_walk_widgets_in_order(sdev, list, fe_params, platform_params,
+					dir, SOF_WIDGET_SETUP);
+	if (ret < 0) {
+		ret = sof_walk_widgets_in_order(sdev, list, fe_params, platform_params,
+						dir, SOF_WIDGET_UNPREPARE);
+		return ret;
+	}
+
 	/*
 	 * error in setting pipeline connections will result in route status being reset for
 	 * routes that were successfully set up when the widgets are freed.
@@ -426,7 +541,9 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, in
 	return 0;
 
 widget_free:
-	sof_setup_or_free_widgets_in_order(sdev, list, dir, SOF_WIDGET_FREE);
+	sof_walk_widgets_in_order(sdev, list, fe_params, platform_params, dir,
+				  SOF_WIDGET_FREE);
+	sof_walk_widgets_in_order(sdev, list, NULL, NULL, dir, SOF_WIDGET_UNPREPARE);
 
 	return ret;
 }
@@ -440,7 +557,11 @@ int sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int
 	if (!list)
 		return 0;
 
-	ret = sof_setup_or_free_widgets_in_order(sdev, list, dir, SOF_WIDGET_FREE);
+	/* send IPC to free widget in the DSP */
+	ret = sof_walk_widgets_in_order(sdev, list, NULL, NULL, dir, SOF_WIDGET_FREE);
+
+	/* unprepare the widget */
+	sof_walk_widgets_in_order(sdev, list, NULL, NULL, dir, SOF_WIDGET_UNPREPARE);
 
 	snd_soc_dapm_dai_free_widgets(&list);
 	spcm->stream[dir].list = NULL;
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index 2db4eb5edcf5..195248d11aaa 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -36,8 +36,10 @@
 #define SOF_DAI_CLK_INTEL_SSP_BCLK	1
 
 enum sof_widget_op {
-	SOF_WIDGET_FREE,
+	SOF_WIDGET_PREPARE,
 	SOF_WIDGET_SETUP,
+	SOF_WIDGET_FREE,
+	SOF_WIDGET_UNPREPARE,
 };
 
 /*
@@ -129,6 +131,8 @@ struct sof_ipc_tplg_control_ops {
  * @token_list: List of token ID's that should be parsed for the widget
  * @token_list_size: number of elements in token_list
  * @bind_event: Function pointer for binding events to the widget
+ * @ipc_prepare: Optional op for preparing a widget for set up
+ * @ipc_unprepare: Optional op for unpreparing a widget
  */
 struct sof_ipc_tplg_widget_ops {
 	int (*ipc_setup)(struct snd_sof_widget *swidget);
@@ -137,6 +141,11 @@ struct sof_ipc_tplg_widget_ops {
 	int token_list_size;
 	int (*bind_event)(struct snd_soc_component *scomp, struct snd_sof_widget *swidget,
 			  u16 event_type);
+	int (*ipc_prepare)(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 *source_params, int dir);
+	void (*ipc_unprepare)(struct snd_sof_widget *swidget);
 };
 
 /**
@@ -332,6 +341,11 @@ struct snd_sof_widget {
 	 * widgets. It is unused for all other widget types.
 	 */
 	int complete;
+	/*
+	 * the prepared flag is used to indicate that a widget has been prepared for getting set
+	 * up in the DSP.
+	 */
+	bool prepared;
 	int use_count; /* use_count will be protected by the PCM mutex held by the core */
 	int core;
 	int id; /* id is the DAPM widget type */
@@ -492,7 +506,10 @@ int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsourc
 		    struct snd_soc_dapm_widget *wsink);
 
 /* PCM */
-int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir);
+int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
+			  struct snd_pcm_hw_params *fe_params,
+			  struct snd_sof_platform_stream_params *platform_params,
+			  int dir);
 int sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir);
 int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, struct snd_sof_dev *sdev,
 			 struct snd_sof_pcm *spcm);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4
  2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
                   ` (10 preceding siblings ...)
  2022-04-26 17:17 ` [PATCH 11/11] ASoC: SOF: Add a prepare op to IPC topology widget ops Ranjani Sridharan
@ 2022-05-03 15:50 ` Mark Brown
  11 siblings, 0 replies; 13+ messages in thread
From: Mark Brown @ 2022-05-03 15:50 UTC (permalink / raw)
  To: ranjani.sridharan, alsa-devel; +Cc: tiwai

On Tue, 26 Apr 2022 10:17:32 -0700, Ranjani Sridharan wrote:
> This series includes last few remaining miscellaneous patches to prepare
> for the introduction of new IPC version, IPC4, in the SOF driver. The changes
> include new IPC ops for topology parsing to set up the volume table, prepare
> the widgets for set up and free the routes. The remaining patches introduce
> new fields in the existing data structures for use in IPC4 and align the flows
> for widget/route set up so that they are common for both IPC3 and IPC4.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[01/11] ASoC: SOF: Add a new op to set up volume table
        commit: 48d2a1ceae03610a431535aca9106eab4201b191
[02/11] ASoC: SOF: sof-audio: reset route status before freeing widget
        commit: 33a3facdf8ccf1b777ef0c39841425ca8d8d4a40
[03/11] ASoC: SOF: sof-audio: Set up widgets from source to sink
        commit: 5da0590a090b096279227cf2b044b1ef9b9c6c1b
[04/11] ASoC: SOF: pcm: Move the call to snd_sof_pcm_platform_hw_params()
        commit: f0d31dbb3fc44ac9cb0d9991cc0a629c88e80ac8
[05/11] ASoC: SOF: expose a couple of functions
        commit: 7b3a5be546a131f806fa015d1c78987daf1eb5c9
[06/11] ASoC: SOF: Add a route_free op in struct sof_ipc_tplg_ops
        commit: d77d7795547ae8e2ed23d1ce835b539ee1d794bb
[07/11] ASoC: SOF: Add two new fields to struct snd_sof_widget
        commit: 36cbc9df3faca01500480acdda016222663da761
[08/11] ASoC: SOF: pcm: remove unnecessary function declaration
        commit: f18ad9caa0dfeb12cb386777b1130c5fba9a0079
[09/11] ASoC: SOF: topology: Skip parsing DAI link tokens if not needed
        commit: a5ba725e9dc928832ba97a4418e36fef8d0244c6
[10/11] ASoC: SOF: clarify use of widget complete flag
        commit: 463a809ba8efa127484d16ff588e3bcdb63fe41e
[11/11] ASoC: SOF: Add a prepare op to IPC topology widget ops
        commit: 66344c6d92113e605d8212e79b1219406893ee05

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2022-05-03 15:52 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-26 17:17 [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Ranjani Sridharan
2022-04-26 17:17 ` [PATCH 01/11] ASoC: SOF: Add a new op to set up volume table Ranjani Sridharan
2022-04-26 17:17 ` [PATCH 02/11] ASoC: SOF: sof-audio: reset route status before freeing widget Ranjani Sridharan
2022-04-26 17:17 ` [PATCH 03/11] ASoC: SOF: sof-audio: Set up widgets from source to sink Ranjani Sridharan
2022-04-26 17:17 ` [PATCH 04/11] ASoC: SOF: pcm: Move the call to snd_sof_pcm_platform_hw_params() Ranjani Sridharan
2022-04-26 17:17 ` [PATCH 05/11] ASoC: SOF: expose a couple of functions Ranjani Sridharan
2022-04-26 17:17 ` [PATCH 06/11] ASoC: SOF: Add a route_free op in struct sof_ipc_tplg_ops Ranjani Sridharan
2022-04-26 17:17 ` [PATCH 07/11] ASoC: SOF: Add two new fields to struct snd_sof_widget Ranjani Sridharan
2022-04-26 17:17 ` [PATCH 08/11] ASoC: SOF: pcm: remove unnecessary function declaration Ranjani Sridharan
2022-04-26 17:17 ` [PATCH 09/11] ASoC: SOF: topology: Skip parsing DAI link tokens if not needed Ranjani Sridharan
2022-04-26 17:17 ` [PATCH 10/11] ASoC: SOF: clarify use of widget complete flag Ranjani Sridharan
2022-04-26 17:17 ` [PATCH 11/11] ASoC: SOF: Add a prepare op to IPC topology widget ops Ranjani Sridharan
2022-05-03 15:50 ` [PATCH 00/11] ASoC: SOF: Miscellaneous preparatory patches for IPC4 Mark Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.