.pcm_open       = hda_dsp_pcm_open,
        .pcm_close      = hda_dsp_pcm_close,
        .pcm_hw_params  = hda_dsp_pcm_hw_params,
+       .pcm_hw_free    = hda_dsp_stream_hw_free,
        .pcm_trigger    = hda_dsp_pcm_trigger,
        .pcm_pointer    = hda_dsp_pcm_pointer,
 
 
        .pcm_open       = hda_dsp_pcm_open,
        .pcm_close      = hda_dsp_pcm_close,
        .pcm_hw_params  = hda_dsp_pcm_hw_params,
+       .pcm_hw_free    = hda_dsp_stream_hw_free,
        .pcm_trigger    = hda_dsp_pcm_trigger,
        .pcm_pointer    = hda_dsp_pcm_pointer,
 
 
        return ret;
 }
 
+int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev,
+                          struct snd_pcm_substream *substream)
+{
+       struct hdac_stream *stream = substream->runtime->private_data;
+       struct hdac_ext_stream *link_dev = container_of(stream,
+                                                       struct hdac_ext_stream,
+                                                       hstream);
+       struct hdac_bus *bus = sof_to_bus(sdev);
+       u32 mask = 0x1 << stream->index;
+
+       spin_lock(&bus->reg_lock);
+       /* couple host and link DMA if link DMA channel is idle */
+       if (!link_dev->link_locked)
+               snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR,
+                                       SOF_HDA_REG_PP_PPCTL, mask, 0);
+       spin_unlock(&bus->reg_lock);
+
+       return 0;
+}
+
 irqreturn_t hda_dsp_stream_interrupt(int irq, void *context)
 {
        struct hdac_bus *bus = context;
 
                          struct snd_pcm_substream *substream,
                          struct snd_pcm_hw_params *params,
                          struct sof_ipc_stream_params *ipc_params);
+int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev,
+                          struct snd_pcm_substream *substream);
 int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev,
                        struct snd_pcm_substream *substream, int cmd);
 snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev,
 
        return 0;
 }
 
+/* host stream hw free */
+static inline int
+snd_sof_pcm_platform_hw_free(struct snd_sof_dev *sdev,
+                            struct snd_pcm_substream *substream)
+{
+       if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_free)
+               return sof_ops(sdev)->pcm_hw_free(sdev, substream);
+
+       return 0;
+}
+
 /* host stream trigger */
 static inline int
 snd_sof_pcm_platform_trigger(struct snd_sof_dev *sdev,
 
 
        cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
 
+       if (ret < 0)
+               return ret;
+
+       ret = snd_sof_pcm_platform_hw_free(sdev, substream);
+       if (ret < 0)
+               dev_err(sdev->dev, "error: platform hw free failed\n");
+
        return ret;
 }
 
 
                             struct snd_pcm_hw_params *params,
                             struct sof_ipc_stream_params *ipc_params); /* optional */
 
+       /* host stream hw_free */
+       int (*pcm_hw_free)(struct snd_sof_dev *sdev,
+                          struct snd_pcm_substream *substream); /* optional */
+
        /* host stream trigger */
        int (*pcm_trigger)(struct snd_sof_dev *sdev,
                           struct snd_pcm_substream *substream,