Unverified Commit 4c87f715 authored by Mark Brown's avatar Mark Brown
Browse files

Merge series "ASoC: SOF: Intel: hda: Enable DMI L1 for power savings" from...

Merge series "ASoC: SOF: Intel: hda: Enable DMI L1 for power savings" from Ranjani Sridharan <ranjani.sridharan@linux.intel.com>:

This series includes 2 patches that enable DMI L1 for D0I3-compatible
streams and trace DMA stream to maximise power savings on Intel
HDA platforms.

v2 changes:
FIx compilation error when probes feature is enabled in SOF Kconfig.

Ranjani Sridharan (2):
  ASoC: SOF: Intel: hda: enable DMI L1 for D0i3-compatible streams
  ASoC: SOF: Intel: hda: Enable DMI L1 for trace

 sound/soc/sof/intel/hda-compress.c |  2 +-
 sound/soc/sof/intel/hda-loader.c   |  2 +-
 sound/soc/sof/intel/hda-pcm.c      | 16 ++++++++++++-
 sound/soc/sof/intel/hda-stream.c   | 38 +++++++++++++++++-------------
 sound/soc/sof/intel/hda-trace.c    |  4 ++--
 sound/soc/sof/intel/hda.h          |  6 ++++-
 6 files changed, 46 insertions(+), 22 deletions(-)

--
2.25.1
parents 9fd5599a 6e021076
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -25,7 +25,7 @@ int hda_probe_compr_assign(struct snd_sof_dev *sdev,
{
{
	struct hdac_ext_stream *stream;
	struct hdac_ext_stream *stream;


	stream = hda_dsp_stream_get(sdev, cstream->direction);
	stream = hda_dsp_stream_get(sdev, cstream->direction, 0);
	if (!stream)
	if (!stream)
		return -EBUSY;
		return -EBUSY;


+1 −1
Original line number Original line Diff line number Diff line
@@ -35,7 +35,7 @@ static struct hdac_ext_stream *cl_stream_prepare(struct snd_sof_dev *sdev, unsig
	struct pci_dev *pci = to_pci_dev(sdev->dev);
	struct pci_dev *pci = to_pci_dev(sdev->dev);
	int ret;
	int ret;


	dsp_stream = hda_dsp_stream_get(sdev, direction);
	dsp_stream = hda_dsp_stream_get(sdev, direction, 0);


	if (!dsp_stream) {
	if (!dsp_stream) {
		dev_err(sdev->dev, "error: no stream available\n");
		dev_err(sdev->dev, "error: no stream available\n");
+15 −1
Original line number Original line Diff line number Diff line
@@ -215,11 +215,25 @@ snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev,
int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
		     struct snd_pcm_substream *substream)
		     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 hdac_ext_stream *dsp_stream;
	struct snd_sof_pcm *spcm;
	int direction = substream->stream;
	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) {
	if (!dsp_stream) {
		dev_err(sdev->dev, "error: no stream available\n");
		dev_err(sdev->dev, "error: no stream available\n");
		return -ENODEV;
		return -ENODEV;
+22 −16
Original line number Original line Diff line number Diff line
@@ -155,7 +155,7 @@ int hda_dsp_stream_spib_config(struct snd_sof_dev *sdev,


/* get next unused stream */
/* get next unused stream */
struct hdac_ext_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 hdac_bus *bus = sof_to_bus(sdev);
	struct sof_intel_hda_stream *hda_stream;
	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);
	spin_unlock_irq(&bus->reg_lock);


	/* stream found ? */
	/* stream found ? */
	if (!stream)
	if (!stream) {
		dev_err(sdev->dev, "error: no free %s streams\n",
		dev_err(sdev->dev, "error: no free %s streams\n",
			direction == SNDRV_PCM_STREAM_PLAYBACK ?
			direction == SNDRV_PCM_STREAM_PLAYBACK ?
			"playback" : "capture");
			"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
	 * Workaround to address a known issue with host DMA that results
	 * in xruns during pause/release in capture scenarios.
	 * in xruns during pause/release in capture scenarios.
	 */
	 */
	if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
	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,
			snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
						HDA_VS_INTEL_EM2,
						HDA_VS_INTEL_EM2,
						HDA_VS_INTEL_EM2_L1SEN, 0);
						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)
int hda_dsp_stream_put(struct snd_sof_dev *sdev, int direction, int stream_tag)
{
{
	struct hdac_bus *bus = sof_to_bus(sdev);
	struct hdac_bus *bus = sof_to_bus(sdev);
	struct sof_intel_hda_stream *hda_stream;
	struct hdac_ext_stream *stream;
	struct hdac_stream *s;
	struct hdac_stream *s;
	bool active_capture_stream = false;
	bool dmi_l1_enable = true;
	bool found = false;
	bool found = false;


	spin_lock_irq(&bus->reg_lock);
	spin_lock_irq(&bus->reg_lock);


	/*
	/*
	 * close stream matching the stream tag
	 * close stream matching the stream tag and check if there are any open streams
	 * and check if there are any open capture streams.
	 * that are DMI L1 incompatible.
	 */
	 */
	list_for_each_entry(s, &bus->stream_list, list) {
	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)
		if (!s->opened)
			continue;
			continue;


		if (s->direction == direction && s->stream_tag == stream_tag) {
		if (s->direction == direction && s->stream_tag == stream_tag) {
			s->opened = false;
			s->opened = false;
			found = true;
			found = true;
		} else if (s->direction == SNDRV_PCM_STREAM_CAPTURE) {
		} else if (!(hda_stream->flags & SOF_HDA_STREAM_DMI_L1_COMPATIBLE)) {
			active_capture_stream = true;
			dmi_l1_enable = false;
		}
		}
	}
	}


	spin_unlock_irq(&bus->reg_lock);
	spin_unlock_irq(&bus->reg_lock);


	/* Enable DMI L1 entry if there are no capture streams open */
	/* Enable DMI L1 if permitted */
	if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1))
	if (!IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1) && dmi_l1_enable)
		if (!active_capture_stream)
		snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2,
			snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
					HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN);
						HDA_VS_INTEL_EM2,
						HDA_VS_INTEL_EM2_L1SEN,
						HDA_VS_INTEL_EM2_L1SEN);


	if (!found) {
	if (!found) {
		dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag);
		dev_dbg(sdev->dev, "stream_tag %d not opened!\n", stream_tag);
+2 −2
Original line number Original line Diff line number Diff line
@@ -42,8 +42,8 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, u32 *stream_tag)
	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
	struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
	int ret;
	int ret;


	hda->dtrace_stream = hda_dsp_stream_get(sdev,
	hda->dtrace_stream = hda_dsp_stream_get(sdev, SNDRV_PCM_STREAM_CAPTURE,
						SNDRV_PCM_STREAM_CAPTURE);
						SOF_HDA_STREAM_DMI_L1_COMPATIBLE);


	if (!hda->dtrace_stream) {
	if (!hda->dtrace_stream) {
		dev_err(sdev->dev,
		dev_err(sdev->dev,
Loading