const struct sof_ipc_ops *ops;
 };
 
+enum sof_dtrace_state {
+       SOF_DTRACE_DISABLED,
+       SOF_DTRACE_STOPPED,
+       SOF_DTRACE_ENABLED,
+};
+
 /*
  * SOF Device Level.
  */
        wait_queue_head_t trace_sleep;
        u32 host_offset;
        bool dtrace_is_supported; /* set with Kconfig or module parameter */
-       bool dtrace_is_enabled;
        bool dtrace_error;
        bool dtrace_draining;
+       enum sof_dtrace_state dtrace_state;
 
        bool msi_enabled;
 
  * Trace/debug
  */
 int snd_sof_init_trace(struct snd_sof_dev *sdev);
-void snd_sof_release_trace(struct snd_sof_dev *sdev);
 void snd_sof_free_trace(struct snd_sof_dev *sdev);
 int snd_sof_dbg_init(struct snd_sof_dev *sdev);
 void snd_sof_free_debug(struct snd_sof_dev *sdev);
                              u32 panic_code, u32 tracep_code, void *oops,
                              struct sof_ipc_panic_info *panic_info,
                              void *stack, size_t stack_words);
-int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev);
+void snd_sof_trace_suspend(struct snd_sof_dev *sdev, pm_message_t pm_state);
+int snd_sof_trace_resume(struct snd_sof_dev *sdev);
 void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev);
 int snd_sof_dbg_memory_info_init(struct snd_sof_dev *sdev);
 int snd_sof_debugfs_add_region_item_iomem(struct snd_sof_dev *sdev,
 
 #include <linux/debugfs.h>
 #include <linux/sched/signal.h>
 #include "sof-priv.h"
+#include "sof-audio.h"
 #include "ops.h"
 #include "sof-utils.h"
 
        if (ret)
                return ret;
 
-       if (!sdev->dtrace_is_enabled && sdev->dtrace_draining) {
+       if (sdev->dtrace_state != SOF_DTRACE_ENABLED && sdev->dtrace_draining) {
                /*
                 * tracing has ended and all traces have been
                 * read by client, return EOF
        struct snd_sof_dev *sdev = dfse->sdev;
 
        /* avoid duplicate traces at next open */
-       if (!sdev->dtrace_is_enabled)
+       if (sdev->dtrace_state != SOF_DTRACE_ENABLED)
                sdev->host_offset = 0;
 
        return 0;
        return 0;
 }
 
-int snd_sof_init_trace_ipc(struct snd_sof_dev *sdev)
+static int snd_sof_enable_trace(struct snd_sof_dev *sdev)
 {
        struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
        struct sof_ipc_fw_version *v = &ready->version;
        if (!sdev->dtrace_is_supported)
                return 0;
 
-       if (sdev->dtrace_is_enabled || !sdev->dma_trace_pages)
+       if (sdev->dtrace_state == SOF_DTRACE_ENABLED || !sdev->dma_trace_pages)
                return -EINVAL;
 
+       if (sdev->dtrace_state == SOF_DTRACE_STOPPED)
+               goto start;
+
        /* set IPC parameters */
        params.hdr.cmd = SOF_IPC_GLB_TRACE_MSG;
        /* PARAMS_EXT is only supported from ABI 3.7.0 onwards */
                goto trace_release;
        }
 
+start:
        ret = snd_sof_dma_trace_trigger(sdev, SNDRV_PCM_TRIGGER_START);
        if (ret < 0) {
                dev_err(sdev->dev,
                goto trace_release;
        }
 
-       sdev->dtrace_is_enabled = true;
+       sdev->dtrace_state = SOF_DTRACE_ENABLED;
 
        return 0;
 
                return 0;
 
        /* set false before start initialization */
-       sdev->dtrace_is_enabled = false;
+       sdev->dtrace_state = SOF_DTRACE_DISABLED;
 
        /* allocate trace page table buffer */
        ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, sdev->dev,
 
        init_waitqueue_head(&sdev->trace_sleep);
 
-       ret = snd_sof_init_trace_ipc(sdev);
+       ret = snd_sof_enable_trace(sdev);
        if (ret < 0)
                goto table_err;
 
        if (!sdev->dtrace_is_supported)
                return 0;
 
-       if (sdev->dtrace_is_enabled && sdev->host_offset != posn->host_offset) {
+       if (sdev->dtrace_state == SOF_DTRACE_ENABLED &&
+           sdev->host_offset != posn->host_offset) {
                sdev->host_offset = posn->host_offset;
                wake_up(&sdev->trace_sleep);
        }
        if (!sdev->dtrace_is_supported)
                return;
 
-       if (sdev->dtrace_is_enabled) {
+       if (sdev->dtrace_state == SOF_DTRACE_ENABLED) {
                sdev->dtrace_error = true;
                wake_up(&sdev->trace_sleep);
        }
 }
 EXPORT_SYMBOL(snd_sof_trace_notify_for_error);
 
-void snd_sof_release_trace(struct snd_sof_dev *sdev)
+static void snd_sof_release_trace(struct snd_sof_dev *sdev, bool only_stop)
 {
        struct sof_ipc_fw_ready *ready = &sdev->fw_ready;
        struct sof_ipc_fw_version *v = &ready->version;
        struct sof_ipc_reply ipc_reply;
        int ret;
 
-       if (!sdev->dtrace_is_supported || !sdev->dtrace_is_enabled)
+       if (!sdev->dtrace_is_supported || sdev->dtrace_state == SOF_DTRACE_DISABLED)
                return;
 
        ret = snd_sof_dma_trace_trigger(sdev, SNDRV_PCM_TRIGGER_STOP);
        if (ret < 0)
                dev_err(sdev->dev,
                        "error: snd_sof_dma_trace_trigger: stop: %d\n", ret);
+       sdev->dtrace_state = SOF_DTRACE_STOPPED;
 
        /*
         * stop and free trace DMA in the DSP. TRACE_DMA_FREE is only supported from
                        dev_err(sdev->dev, "DMA_TRACE_FREE failed with error: %d\n", ret);
        }
 
+       if (only_stop)
+               goto out;
+
        ret = snd_sof_dma_trace_release(sdev);
        if (ret < 0)
                dev_err(sdev->dev,
                        "error: fail in snd_sof_dma_trace_release %d\n", ret);
 
-       sdev->dtrace_is_enabled = false;
+       sdev->dtrace_state = SOF_DTRACE_DISABLED;
+
+out:
        sdev->dtrace_draining = true;
        wake_up(&sdev->trace_sleep);
 }
-EXPORT_SYMBOL(snd_sof_release_trace);
+
+void snd_sof_trace_suspend(struct snd_sof_dev *sdev, pm_message_t pm_state)
+{
+       snd_sof_release_trace(sdev, pm_state.event == SOF_DSP_PM_D0);
+}
+EXPORT_SYMBOL(snd_sof_trace_suspend);
+
+int snd_sof_trace_resume(struct snd_sof_dev *sdev)
+{
+       return snd_sof_enable_trace(sdev);
+}
+EXPORT_SYMBOL(snd_sof_trace_resume);
 
 void snd_sof_free_trace(struct snd_sof_dev *sdev)
 {
        if (!sdev->dtrace_is_supported)
                return;
 
-       snd_sof_release_trace(sdev);
+       /* release trace */
+       snd_sof_release_trace(sdev, false);
 
        if (sdev->dma_trace_pages) {
                snd_dma_free_pages(&sdev->dmatb);