]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ASoC: SOF: Relocate and rework functionality for PCM stream freeing
authorPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Thu, 6 Feb 2025 09:28:25 +0000 (11:28 +0200)
committerMark Brown <broonie@kernel.org>
Thu, 6 Feb 2025 11:25:41 +0000 (11:25 +0000)
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@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://patch.msgid.link/20250206092828.7569-2-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/ipc3-topology.c
sound/soc/sof/ipc4-topology.c
sound/soc/sof/pcm.c
sound/soc/sof/sof-audio.c
sound/soc/sof/sof-audio.h

index e98b53b67d12b9340b2acb97429b74f7a3de5b35..473d416bc91064a8750011e7e9114b7714f5106c 100644 (file)
@@ -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
index c04c62478827a5e268c71cb82e29f32b99a2a256..21e29bfd4b22c939c0b63527a5d5ba54ecb94683 100644 (file)
@@ -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)
index 35a7462d8b69385a7565a2401f476926b37837ac..709baa1b0bd6e05fee9228b68198becfeb200e22 100644 (file)
@@ -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)
 {
index 9a52781bf8d8b97330a19999b9f874fd25eda80f..a9664b4cf43f9069d85c2156bea14969b8d21dd1 100644 (file)
@@ -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.
  */
index 62f3c11a9216de8ba4a9a7d258e8d0a541ee82db..7d48109246825e5486f9ca26203bbfbc6e4bbe0c 100644 (file)
@@ -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);