case snd_soc_dapm_buffer:
                ipc_free.hdr.cmd |= SOF_IPC_TPLG_BUFFER_FREE;
                break;
+       case snd_soc_dapm_dai_in:
+       case snd_soc_dapm_dai_out:
+       {
+               struct snd_sof_dai *dai = swidget->private;
+
+               dai->configured = false;
+               fallthrough;
+       }
        default:
                ipc_free.hdr.cmd |= SOF_IPC_TPLG_COMP_FREE;
                break;
        return 0;
 }
 
+/*
+ * 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.
+ */
+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;
+
+       /*
+        * 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)
+                               continue;
+
+                       if (spcm->stream[dir].list) {
+                               ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
+                               if (ret < 0)
+                                       return ret;
+
+                               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 any left over DAI widgets. This is equivalent to the handling of suspend trigger
+        * for the BE DAI for running streams.
+        */
+       list_for_each_entry(swidget, &sdev->widget_list, list)
+               if (WIDGET_IS_DAI(swidget->id) && swidget->use_count == 1) {
+                       ret = sof_widget_free(sdev, swidget);
+                       if (ret < 0)
+                               return ret;
+               }
+
+       return 0;
+}
+
 /*
  * For older firmware, this function doesn't free widgets for static pipelines during suspend.
  * It only resets use_count for all widgets.
        /*
         * This function is called during suspend and for one-time topology verification during
         * first boot. In both cases, there is no need to protect swidget->use_count and
-        * sroute->setup because during suspend all streams are suspended and during topology
-        * loading the sound card unavailable to open PCMs.
+        * sroute->setup because during suspend all running streams are suspended and during
+        * topology loading the sound card unavailable to open PCMs.
         */
        list_for_each_entry(swidget, &sdev->widget_list, list) {
                if (swidget->dynamic_pipeline_widget)
                        return ret;
        }
 
+       /*
+        * Tear down all pipelines associated with PCMs that did not get suspended
+        * and unset the prepare flag so that they can be set up again during resume.
+        * Skip this step for older firmware.
+        */
+       if (!verify && v->abi_version >= SOF_ABI_VER(3, 19, 0)) {
+               ret = sof_tear_down_left_over_pipelines(sdev);
+               if (ret < 0) {
+                       dev_err(sdev->dev, "failed to tear down paused pipelines\n");
+                       return ret;
+               }
+       }
+
        list_for_each_entry(sroute, &sdev->route_list, list)
                sroute->setup = false;