OSDN Git Service

ASoC: SOF: Add a helper for freeing PCM stream
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Thu, 25 Nov 2021 10:15:16 +0000 (12:15 +0200)
committerMark Brown <broonie@kernel.org>
Fri, 26 Nov 2021 13:24:21 +0000 (13:24 +0000)
Add a helper function to free PCM in the FW, stop the DMA and free the
widget list. These actions are performed both during PCM trigger STOP
and when a paused stream is freed during system suspend.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/20211125101520.291581-7-kai.vehmanen@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/pcm.c
sound/soc/sof/sof-audio.c
sound/soc/sof/sof-audio.h

index 1d0d905..3aa708b 100644 (file)
@@ -466,17 +466,10 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
 
        /* free PCM if reset_hw_params is set and the STOP IPC is successful */
        if (!ret && reset_hw_params) {
-               ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
+               ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream,
+                                         free_widget_list);
                if (ret < 0)
                        return ret;
-
-               ret = snd_sof_pcm_platform_hw_free(sdev, substream);
-               if (ret < 0)
-                       return ret;
-
-               /* free widget list only for SUSPEND trigger */
-               if (free_widget_list)
-                       ret = sof_widget_list_free(sdev, spcm, substream->stream);
        }
 
        return ret;
index d81071b..a275f7b 100644 (file)
@@ -728,6 +728,31 @@ int sof_set_up_pipelines(struct snd_sof_dev *sdev, bool verify)
        return 0;
 }
 
+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 ret;
+
+       /* Send PCM_FREE IPC to reset pipeline */
+       ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
+       if (ret < 0)
+               return ret;
+
+       /* stop the DMA */
+       ret = snd_sof_pcm_platform_hw_free(sdev, substream);
+       if (ret < 0)
+               return ret;
+
+       /* free widget list */
+       if (free_widget_list) {
+               ret = sof_widget_list_free(sdev, spcm, dir);
+               if (ret < 0)
+                       dev_err(sdev->dev, "failed to free widgets during suspend\n");
+       }
+
+       return ret;
+}
+
 /*
  * Free the PCM, its associated widgets and set the prepared flag to false for all PCMs that
  * did not get suspended(ex: paused streams) so the widgets can be set up again during resume.
@@ -751,22 +776,9 @@ static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev)
                                continue;
 
                        if (spcm->stream[dir].list) {
-                               /* Free PCM in the DSP */
-                               ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
-                               if (ret < 0)
-                                       return ret;
-
-                               /* stop DMA */
-                               ret = snd_sof_pcm_platform_hw_free(sdev, substream);
+                               ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true);
                                if (ret < 0)
                                        return ret;
-
-                               /* free the DAPM widget list */
-                               ret = sof_widget_list_free(sdev, spcm, dir);
-                               if (ret < 0) {
-                                       dev_err(sdev->dev, "failed to free widgets during suspend\n");
-                                       return ret;
-                               }
                        }
                }
 
index 1c4f59d..e419e70 100644 (file)
@@ -267,4 +267,6 @@ 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);
 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);
 #endif