int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
                     struct snd_pcm_substream *substream)
 {
+       struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+       struct snd_soc_component *scomp = sdev->component;
        struct hdac_ext_stream *dsp_stream;
+       struct snd_sof_pcm *spcm;
        int direction = substream->stream;
+       u32 flags = 0;
+
+       spcm = snd_sof_find_spcm_dai(scomp, rtd);
+       if (!spcm) {
+               dev_err(sdev->dev, "error: can't find PCM with DAI ID %d\n", rtd->dai_link->id);
+               return -EINVAL;
+       }
 
-       dsp_stream = hda_dsp_stream_get(sdev, direction);
+       /* All playback and D0i3 compatible streams are DMI L1 capable */
+       if (direction == SNDRV_PCM_STREAM_PLAYBACK ||
+           spcm->stream[substream->stream].d0i3_compatible)
+               flags |= SOF_HDA_STREAM_DMI_L1_COMPATIBLE;
 
+       dsp_stream = hda_dsp_stream_get(sdev, direction, flags);
        if (!dsp_stream) {
                dev_err(sdev->dev, "error: no stream available\n");
                return -ENODEV;
 
 
 /* get next unused stream */
 struct hdac_ext_stream *
-hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction)
+hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags)
 {
        struct hdac_bus *bus = sof_to_bus(sdev);
        struct sof_intel_hda_stream *hda_stream;
        spin_unlock_irq(&bus->reg_lock);
 
        /* stream found ? */
-       if (!stream)
+       if (!stream) {
                dev_err(sdev->dev, "error: no free %s streams\n",
                        direction == SNDRV_PCM_STREAM_PLAYBACK ?
                        "playback" : "capture");
+               return stream;
+       }
+
+       hda_stream->flags = flags;
 
        /*
-        * Disable DMI Link L1 entry when capture stream is opened.
+        * Prevent DMI Link L1 entry for streams that don't support it.
         * Workaround to address a known issue with host DMA that results
         * in xruns during pause/release in capture scenarios.
         */
        if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
-               if (stream && direction == SNDRV_PCM_STREAM_CAPTURE)
+               if (stream && !(flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE))
                        snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
                                                HDA_VS_INTEL_EM2,
                                                HDA_VS_INTEL_EM2_L1SEN, 0);
 int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag)
 {
        struct hdac_bus *bus = sof_to_bus(sdev);
+       struct sof_intel_hda_stream *hda_stream;
+       struct hdac_ext_stream *stream;
        struct hdac_stream *s;
-       bool active_capture_stream = false;
+       bool dmi_l1_enable = true;
        bool found = false;
 
        spin_lock_irq(&bus->reg_lock);
 
        /*
-        * close stream matching the stream tag
-        * and check if there are any open capture streams.
+        * close stream matching the stream tag and check if there are any open streams
+        * that are DMI L1 incompatible.
         */
        list_for_each_entry(s, &bus->stream_list, list) {
+               stream = stream_to_hdac_ext_stream(s);
+               hda_stream = container_of(stream, struct sof_intel_hda_stream, hda_stream);
+
                if (!s->opened)
                        continue;
 
                if (s->direction == direction && s->stream_tag == stream_tag) {
                        s->opened = false;
                        found = true;
-               } else if (s->direction == SNDRV_PCM_STREAM_CAPTURE) {
-                       active_capture_stream = true;
+               } else if (!(hda_stream->flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) {
+                       dmi_l1_enable = false;
                }
        }
 
        spin_unlock_irq(&bus->reg_lock);
 
-       /* Enable DMI L1 entry if there are no capture streams open */
-       if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
-               if (!active_capture_stream)
-                       snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
-                                               HDA_VS_INTEL_EM2,
-                                               HDA_VS_INTEL_EM2_L1SEN,
-                                               HDA_VS_INTEL_EM2_L1SEN);
+       /* Enable DMI L1 if permitted */
+       if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1) && dmi_l1_enable)
+               snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2,
+                                       HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN);
 
        if (!found) {
                dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag);
 
 #define SOF_HDA_PLAYBACK               0
 #define SOF_HDA_CAPTURE                        1
 
+/* stream flags */
+#define SOF_HDA_STREAM_DMI_L1_COMPATIBLE       1
+
 /*
  * Time in ms for opportunistic D0I3 entry delay.
  * This has been deliberately chosen to be long to avoid race conditions.
        struct hdac_ext_stream hda_stream;
        struct sof_intel_stream stream;
        int host_reserved; /* reserve host DMA channel */
+       u32 flags;
 };
 
 #define hstream_to_sof_hda_stream(hstream) \
 bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev);
 
 struct hdac_ext_stream *
-       hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction);
+       hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags);
 int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag);
 int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,
                               struct hdac_ext_stream *stream,