ASoC: SOF: Intel: hda-dsp: Set streaming flag for d0i3
authorRander Wang <rander.wang@intel.com>
Tue, 14 Feb 2023 10:33:45 +0000 (12:33 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 14 Feb 2023 13:25:15 +0000 (13:25 +0000)
Enable d0i3 streaming if all the active streams can
work in d0i3 state and playback is enabled.

Signed-off-by: Rander Wang <rander.wang@intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20230214103345.30669-6-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/intel/hda-dsp.c

index e34fe0c9bcde04a0693932071ac8ed274828a2aa..68eb06f13a1fd2539bab66cf9c255d860e059caf 100644 (file)
@@ -405,6 +405,34 @@ static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value)
        return 0;
 }
 
+/*
+ * d0i3 streaming is enabled if all the active streams can
+ * work in d0i3 state and playback is enabled
+ */
+static bool hda_dsp_d0i3_streaming_applicable(struct snd_sof_dev *sdev)
+{
+       struct snd_pcm_substream *substream;
+       struct snd_sof_pcm *spcm;
+       bool playback_active = false;
+       int dir;
+
+       list_for_each_entry(spcm, &sdev->pcm_list, list) {
+               for_each_pcm_streams(dir) {
+                       substream = spcm->stream[dir].substream;
+                       if (!substream || !substream->runtime)
+                               continue;
+
+                       if (!spcm->stream[dir].d0i3_compatible)
+                               return false;
+
+                       if (dir == SNDRV_PCM_STREAM_PLAYBACK)
+                               playback_active = true;
+               }
+       }
+
+       return playback_active;
+}
+
 static int hda_dsp_set_D0_state(struct snd_sof_dev *sdev,
                                const struct sof_dsp_power_state *target_state)
 {
@@ -446,6 +474,9 @@ static int hda_dsp_set_D0_state(struct snd_sof_dev *sdev,
                    !hda_enable_trace_D0I3_S0 ||
                    sdev->system_suspend_target != SOF_SUSPEND_NONE)
                        flags = HDA_PM_NO_DMA_TRACE;
+
+               if (hda_dsp_d0i3_streaming_applicable(sdev))
+                       flags |= HDA_PM_PG_STREAMING;
        } else {
                /* prevent power gating in D0I0 */
                flags = HDA_PM_PPG;