Move the sof_pcm_stream_free() from sof-audio.c to pcm.c as static function
and add wrapper to free all active stream, which is going to be used in
ipc3/4 topology code (removes duplicated code).
With this change most of the PCM stream related code is located in one
source file for easier lookup and simplified flow.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@xxxxxxxxxxxxxxx>
Reviewed-by: Liam Girdwood <liam.r.girdwood@xxxxxxxxx>
Reviewed-by: Bard Liao <yung-chuan.liao@xxxxxxxxxxxxxxx>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@xxxxxxxxxxxxxxx>
---
sound/soc/sof/ipc3-topology.c | 20 ++-------
sound/soc/sof/ipc4-topology.c | 18 +-------
sound/soc/sof/pcm.c | 78 +++++++++++++++++++++++++++++++++++
sound/soc/sof/sof-audio.c | 49 ----------------------
sound/soc/sof/sof-audio.h | 3 +-
5 files changed, 84 insertions(+), 84 deletions(-)
diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c
index e98b53b67d12..473d416bc910 100644
--- a/sound/soc/sof/ipc3-topology.c
+++ b/sound/soc/sof/ipc3-topology.c
@@ -2386,28 +2386,16 @@ static int sof_ipc3_set_up_all_pipelines(struct snd_sof_dev *sdev, bool verify)
static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev)
{
struct snd_sof_widget *swidget;
- struct snd_sof_pcm *spcm;
- int dir, ret;
+ int ret;
/*
* free all PCMs and their associated DAPM widgets if their connected DAPM widget
* list is not NULL. This should only be true for paused streams at this point.
* This is equivalent to the handling of FE DAI suspend trigger for running streams.
*/
- list_for_each_entry(spcm, &sdev->pcm_list, list) {
- for_each_pcm_streams(dir) {
- struct snd_pcm_substream *substream = spcm->stream[dir].substream;
-
- if (!substream || !substream->runtime || spcm->stream[dir].suspend_ignored)
- continue;
-
- if (spcm->stream[dir].list) {
- ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true);
- if (ret < 0)
- return ret;
- }
- }
- }
+ ret = sof_pcm_free_all_streams(sdev);
+ if (ret)
+ return ret;
/*
* free any left over DAI widgets. This is equivalent to the handling of suspend trigger
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index c04c62478827..21e29bfd4b22 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -3401,9 +3401,6 @@ static int sof_ipc4_dai_get_param(struct snd_sof_dev *sdev, struct snd_sof_dai *
static int sof_ipc4_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify)
{
- struct snd_sof_pcm *spcm;
- int dir, ret;
-
/*
* This function is called during system suspend, we need to make sure
* that all streams have been freed up.
@@ -3415,21 +3412,8 @@ static int sof_ipc4_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif
*
* This will also make sure that paused streams handled correctly.
*/
- list_for_each_entry(spcm, &sdev->pcm_list, list) {
- for_each_pcm_streams(dir) {
- struct snd_pcm_substream *substream = spcm->stream[dir].substream;
-
- if (!substream || !substream->runtime || spcm->stream[dir].suspend_ignored)
- continue;
- if (spcm->stream[dir].list) {
- ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true);
- if (ret < 0)
- return ret;
- }
- }
- }
- return 0;
+ return sof_pcm_free_all_streams(sdev);
}
static int sof_ipc4_link_setup(struct snd_sof_dev *sdev, struct snd_soc_dai_link *link)
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
index 35a7462d8b69..709baa1b0bd6 100644
--- a/sound/soc/sof/pcm.c
+++ b/sound/soc/sof/pcm.c
@@ -191,6 +191,84 @@ static int sof_pcm_hw_params(struct snd_soc_component *component,
return 0;
}
+static int sof_pcm_stream_free(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+ struct snd_sof_pcm *spcm, int dir,
+ bool free_widget_list)
+{
+ const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
+ int ret;
+ int err = 0;
+
+ if (spcm->prepared[substream->stream]) {
+ /* stop DMA first if needed */
+ if (pcm_ops && pcm_ops->platform_stop_during_hw_free)
+ snd_sof_pcm_platform_trigger(sdev, substream,
+ SNDRV_PCM_TRIGGER_STOP);
+
+ /* free PCM in the DSP */
+ if (pcm_ops && pcm_ops->hw_free) {
+ ret = pcm_ops->hw_free(sdev->component, substream);
+ if (ret < 0) {
+ dev_err(sdev->dev, "%s: pcm_ops hw_free failed %d\n",
+ __func__, ret);
+ err = ret;
+ }
+ }
+
+ spcm->prepared[substream->stream] = false;
+ spcm->pending_stop[substream->stream] = false;
+ }
+
+ /* reset the DMA */
+ ret = snd_sof_pcm_platform_hw_free(sdev, substream);
+ if (ret < 0) {
+ dev_err(sdev->dev, "%s: platform hw free failed %d\n",
+ __func__, ret);
+ if (!err)
+ err = ret;
+ }
+
+ /* free widget list */
+ if (free_widget_list) {
+ ret = sof_widget_list_free(sdev, spcm, dir);
+ if (ret < 0) {
+ dev_err(sdev->dev, "%s: sof_widget_list_free failed %d\n",
+ __func__, ret);
+ if (!err)
+ err = ret;
+ }
+ }
+
+ return err;
+}
+
+int sof_pcm_free_all_streams(struct snd_sof_dev *sdev)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_sof_pcm *spcm;
+ int dir, ret;
+
+ list_for_each_entry(spcm, &sdev->pcm_list, list) {
+ for_each_pcm_streams(dir) {
+ substream = spcm->stream[dir].substream;
+
+ if (!substream || !substream->runtime ||
+ spcm->stream[dir].suspend_ignored)
+ continue;
+
+ if (spcm->stream[dir].list) {
+ ret = sof_pcm_stream_free(sdev, substream, spcm,
+ dir, true);
+ if (ret < 0)
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
static int sof_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c
index 9a52781bf8d8..a9664b4cf43f 100644
--- a/sound/soc/sof/sof-audio.c
+++ b/sound/soc/sof/sof-audio.c
@@ -829,55 +829,6 @@ bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev)
return false;
}
-int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream,
- struct snd_sof_pcm *spcm, int dir, bool free_widget_list)
-{
- const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
- int ret;
- int err = 0;
-
- if (spcm->prepared[substream->stream]) {
- /* stop DMA first if needed */
- if (pcm_ops && pcm_ops->platform_stop_during_hw_free)
- snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP);
-
- /* free PCM in the DSP */
- if (pcm_ops && pcm_ops->hw_free) {
- ret = pcm_ops->hw_free(sdev->component, substream);
- if (ret < 0) {
- dev_err(sdev->dev, "%s: pcm_ops hw_free failed %d\n",
- __func__, ret);
- err = ret;
- }
- }
-
- spcm->prepared[substream->stream] = false;
- spcm->pending_stop[substream->stream] = false;
- }
-
- /* reset the DMA */
- ret = snd_sof_pcm_platform_hw_free(sdev, substream);
- if (ret < 0) {
- dev_err(sdev->dev, "%s: platform hw free failed %d\n",
- __func__, ret);
- if (!err)
- err = ret;
- }
-
- /* free widget list */
- if (free_widget_list) {
- ret = sof_widget_list_free(sdev, spcm, dir);
- if (ret < 0) {
- dev_err(sdev->dev, "%s: sof_widget_list_free failed %d\n",
- __func__, ret);
- if (!err)
- err = ret;
- }
- }
-
- return err;
-}
-
/*
* Generic object lookup APIs.
*/
diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
index 62f3c11a9216..7d4810924682 100644
--- a/sound/soc/sof/sof-audio.h
+++ b/sound/soc/sof/sof-audio.h
@@ -649,8 +649,7 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm,
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);
-int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream,
- struct snd_sof_pcm *spcm, int dir, bool free_widget_list);
+int sof_pcm_free_all_streams(struct snd_sof_dev *sdev);
int get_token_u32(void *elem, void *object, u32 offset);
int get_token_u16(void *elem, void *object, u32 offset);
int get_token_comp_format(void *elem, void *object, u32 offset);
--
2.48.1
[Index of Archives]
[Pulseaudio]
[Linux Audio Users]
[ALSA Devel]
[Fedora Desktop]
[Fedora SELinux]
[Big List of Linux Books]
[Yosemite News]
[KDE Users]