Unverified Commit d9a72465 authored by Ranjani Sridharan's avatar Ranjani Sridharan Committed by Mark Brown
Browse files

ASoC: SOF: Add a helper for freeing PCM stream



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: default avatarRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: default avatarKai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/20211125101520.291581-7-kai.vehmanen@linux.intel.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 47934e0f
Loading
Loading
Loading
Loading
+2 −9
Original line number Diff line number Diff line
@@ -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;
+26 −14
Original line number Diff line number Diff line
@@ -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);
				ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true);
				if (ret < 0)
					return ret;

				/* stop DMA */
				ret = snd_sof_pcm_platform_hw_free(sdev, substream);
				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;
				}
			}
		}

+2 −0
Original line number Diff line number Diff line
@@ -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