ASoC: SOF: pcm: do not free widgets during suspend trigger
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Fri, 27 Jan 2023 12:00:18 +0000 (14:00 +0200)
committerMark Brown <broonie@kernel.org>
Fri, 27 Jan 2023 12:14:02 +0000 (12:14 +0000)
IPC3 and IPC4 have different requirements for the order in which the FE
CPU and BE CPU DAI trigger callbacks must be invoked. With a regular PCM
start/stop, pipeline widgets are set up during hw_params and freed
during hw_free.

But when the system is suspended when a PCM is running,
pipeline widgets are freed during the SUSPEND trigger callback for the
FE CPU DAI. In order to avoid freeing the pipeline widgets before the BE
CPU DAI trigger is executed, the trigger order was modified in previous
contributions in the PCM dai_link_fixup callback to make sure that the BE
CPU DAI trigger stop/suspend is always invoked before the FE CPU DAI
trigger. But this contradicts the firmware requirement for IPC4 w.r.t.
ordering of pipeline triggers.

So, remove the freeing of pipeline widgets during FE CPU DAI suspend
trigger and handle it during system suspend when the
tear_down_all_pipelines() IPC op is invoked. This will be followed up
with a patch to fix the trigger order for 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>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20230127120031.10709-6-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/ipc3-topology.c
sound/soc/sof/ipc4-pcm.c
sound/soc/sof/ipc4-topology.c
sound/soc/sof/pcm.c

index 989395999d6ec052656ee2202f94e8da760336d9..72ac1725af0d9fc3f35892a794ccb1283817c49f 100644 (file)
@@ -2264,7 +2264,7 @@ static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev)
                for_each_pcm_streams(dir) {
                        struct snd_pcm_substream *substream = spcm->stream[dir].substream;
 
-                       if (!substream || !substream->runtime)
+                       if (!substream || !substream->runtime || spcm->stream[dir].suspend_ignored)
                                continue;
 
                        if (spcm->stream[dir].list) {
index 96941bebc1f19ecc59ff48316855a69762c7f941..23de58d7d06b384a3cbf3039ec2cdd3773f4b95a 100644 (file)
@@ -183,7 +183,6 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
        struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
        struct sof_ipc4_copier *ipc4_copier;
-       struct snd_soc_dpcm *dpcm;
 
        if (!dai) {
                dev_err(component->dev, "%s: No DAI found with name %s\n", __func__,
@@ -205,17 +204,6 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
        rate->min = ipc4_copier->available_fmt.base_config->audio_fmt.sampling_frequency;
        rate->max = rate->min;
 
-       /*
-        * Set trigger order for capture to SND_SOC_DPCM_TRIGGER_PRE. This is required
-        * to ensure that the BE DAI pipeline gets stopped/suspended before the FE DAI
-        * pipeline gets triggered and the pipeline widgets are freed.
-        */
-       for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_CAPTURE, dpcm) {
-               struct snd_soc_pcm_runtime *fe = dpcm->fe;
-
-               fe->dai_link->trigger[SNDRV_PCM_STREAM_CAPTURE] = SND_SOC_DPCM_TRIGGER_PRE;
-       }
-
        switch (ipc4_copier->dai_type) {
        case SOF_DAI_INTEL_SSP:
                ipc4_ssp_dai_config_pcm_params_match(sdev, (char *)rtd->dai_link->name, params);
index ae8ec98bb4eb3a72a8e66b8ceabae62a11e5516e..3938ff2d998b959d79896357e3d50a7fe4b0c783 100644 (file)
@@ -2025,7 +2025,7 @@ static int sof_ipc4_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif
                for_each_pcm_streams(dir) {
                        struct snd_pcm_substream *substream = spcm->stream[dir].substream;
 
-                       if (!substream || !substream->runtime)
+                       if (!substream || !substream->runtime || spcm->stream[dir].suspend_ignored)
                                continue;
 
                        if (spcm->stream[dir].list) {
index 952fc698a5861710d34fccd69e40856e1b4b5369..34d40c5c629a2bd0a804d5e4a74c24f84577baa1 100644 (file)
@@ -282,7 +282,6 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
        const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
        struct snd_sof_pcm *spcm;
        bool reset_hw_params = false;
-       bool free_widget_list = false;
        bool ipc_first = false;
        int ret = 0;
 
@@ -326,7 +325,6 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
                        spcm->stream[substream->stream].suspend_ignored = true;
                        return 0;
                }
-               free_widget_list = true;
                fallthrough;
        case SNDRV_PCM_TRIGGER_STOP:
                ipc_first = true;
@@ -353,8 +351,7 @@ 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_stream_free(sdev, substream, spcm, substream->stream,
-                                         free_widget_list);
+               ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, false);
 
        return ret;
 }