diff options
author | Ranjani Sridharan <ranjani.sridharan@linux.intel.com> | 2021-01-26 18:07:36 -0800 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2021-01-27 13:06:49 +0000 |
commit | 89a400bdeb129dbc7e1c8ad2151cc8141a619709 (patch) | |
tree | 41ef0e92cbbbbb0c94d225ead6da18a5ac36402c /sound/soc/sof/intel/hda-stream.c | |
parent | ed9ce1ed2239909c23d48c723c6549417c476246 (diff) |
ASoC: SOF: Intel: hda: enable DMI L1 for D0i3-compatible streams
DMI L1 entry is currently disabled whenever any capture stream is
opened to prevent xruns during pause/release. But, in
order to maximise power savings for the wake-on-voice usecase,
DMI L1 entry should be enabled for D0i3-compatible capture streams.
Introduce a new field, flags in struct sof_intel_hda_stream
that stores whether a stream is dmi_l1_compatible. All playback streams,
and D0i3-compatible capture streams are DMI L1 compatible.
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Link: https://lore.kernel.org/r/20210127020737.1088960-2-ranjani.sridharan@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/sof/intel/hda-stream.c')
-rw-r--r-- | sound/soc/sof/intel/hda-stream.c | 38 |
1 files changed, 22 insertions, 16 deletions
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 0e09ede922c7..40a3993ae2cb 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -155,7 +155,7 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev, /* 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; @@ -183,18 +183,22 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction) 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); @@ -206,37 +210,39 @@ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction) 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); |