Merge tag 'sound-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[linux-block.git] / sound / soc / sof / intel / hda-dsp.c
index a6f2822401e03da1d3553f50fa4370955219f6e2..44f39a520bb39cc44e068231a817846c77b8b0a9 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <sound/hdaudio_ext.h>
 #include <sound/hda_register.h>
+#include <sound/hda-mlink.h>
 #include <trace/events/sof_intel.h>
 #include "../sof-audio.h"
 #include "../ops.h"
@@ -321,6 +322,9 @@ void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev)
        struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
        const struct sof_intel_dsp_desc *chip = hda->desc;
 
+       if (sdev->dspless_mode_selected)
+               return;
+
        /* enable IPC DONE and BUSY interrupts */
        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
                        HDA_DSP_REG_HIPCCTL_DONE | HDA_DSP_REG_HIPCCTL_BUSY,
@@ -336,6 +340,9 @@ void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev)
        struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
        const struct sof_intel_dsp_desc *chip = hda->desc;
 
+       if (sdev->dspless_mode_selected)
+               return;
+
        /* disable IPC interrupt */
        snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC,
                                HDA_DSP_ADSPIC_IPC, 0);
@@ -567,31 +574,11 @@ static void hda_dsp_state_log(struct snd_sof_dev *sdev)
  * is called again either because of a new IPC sent to the DSP or
  * during system suspend/resume.
  */
-int hda_dsp_set_power_state(struct snd_sof_dev *sdev,
-                           const struct sof_dsp_power_state *target_state)
+static int hda_dsp_set_power_state(struct snd_sof_dev *sdev,
+                                  const struct sof_dsp_power_state *target_state)
 {
        int ret = 0;
 
-       /*
-        * When the DSP is already in D0I3 and the target state is D0I3,
-        * it could be the case that the DSP is in D0I3 during S0
-        * and the system is suspending to S0Ix. Therefore,
-        * hda_dsp_set_D0_state() must be called to disable trace DMA
-        * by sending the PM_GATE IPC to the FW.
-        */
-       if (target_state->substate == SOF_HDA_DSP_PM_D0I3 &&
-           sdev->system_suspend_target == SOF_SUSPEND_S0IX)
-               goto set_state;
-
-       /*
-        * For all other cases, return without doing anything if
-        * the DSP is already in the target state.
-        */
-       if (target_state->state == sdev->dsp_power_state.state &&
-           target_state->substate == sdev->dsp_power_state.substate)
-               return 0;
-
-set_state:
        switch (target_state->state) {
        case SOF_DSP_PM_D0:
                ret = hda_dsp_set_D0_state(sdev, target_state);
@@ -623,6 +610,42 @@ set_state:
        return ret;
 }
 
+int hda_dsp_set_power_state_ipc3(struct snd_sof_dev *sdev,
+                                const struct sof_dsp_power_state *target_state)
+{
+       /*
+        * When the DSP is already in D0I3 and the target state is D0I3,
+        * it could be the case that the DSP is in D0I3 during S0
+        * and the system is suspending to S0Ix. Therefore,
+        * hda_dsp_set_D0_state() must be called to disable trace DMA
+        * by sending the PM_GATE IPC to the FW.
+        */
+       if (target_state->substate == SOF_HDA_DSP_PM_D0I3 &&
+           sdev->system_suspend_target == SOF_SUSPEND_S0IX)
+               return hda_dsp_set_power_state(sdev, target_state);
+
+       /*
+        * For all other cases, return without doing anything if
+        * the DSP is already in the target state.
+        */
+       if (target_state->state == sdev->dsp_power_state.state &&
+           target_state->substate == sdev->dsp_power_state.substate)
+               return 0;
+
+       return hda_dsp_set_power_state(sdev, target_state);
+}
+
+int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev,
+                                const struct sof_dsp_power_state *target_state)
+{
+       /* Return without doing anything if the DSP is already in the target state */
+       if (target_state->state == sdev->dsp_power_state.state &&
+           target_state->substate == sdev->dsp_power_state.substate)
+               return 0;
+
+       return hda_dsp_set_power_state(sdev, target_state);
+}
+
 /*
  * Audio DSP states may transform as below:-
  *
@@ -681,6 +704,9 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
        /* power down all hda links */
        hda_bus_ml_suspend(bus);
 
+       if (sdev->dspless_mode_selected)
+               goto skip_dsp;
+
        ret = chip->power_down_dsp(sdev);
        if (ret < 0) {
                dev_err(sdev->dev, "failed to power down DSP during suspend\n");
@@ -694,6 +720,7 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
        /* disable ppcap interrupt */
        hda_dsp_ctrl_ppcap_enable(sdev, false);
        hda_dsp_ctrl_ppcap_int_enable(sdev, false);
+skip_dsp:
 
        /* disable hda bus irq and streams */
        hda_dsp_ctrl_stop_chip(sdev);
@@ -744,9 +771,11 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume)
                        hda_codec_jack_check(sdev);
        }
 
-       /* enable ppcap interrupt */
-       hda_dsp_ctrl_ppcap_enable(sdev, true);
-       hda_dsp_ctrl_ppcap_int_enable(sdev, true);
+       if (!sdev->dspless_mode_selected) {
+               /* enable ppcap interrupt */
+               hda_dsp_ctrl_ppcap_enable(sdev, true);
+               hda_dsp_ctrl_ppcap_int_enable(sdev, true);
+       }
 
 cleanup:
        /* display codec can powered off after controller init */
@@ -788,7 +817,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev)
                }
 
                /* restore L1SEN bit */
-               if (hda->l1_support_changed)
+               if (hda->l1_disabled)
                        snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
                                                HDA_VS_INTEL_EM2,
                                                HDA_VS_INTEL_EM2_L1SEN, 0);
@@ -843,8 +872,10 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev)
        };
        int ret;
 
-       /* cancel any attempt for DSP D0I3 */
-       cancel_delayed_work_sync(&hda->d0i3_work);
+       if (!sdev->dspless_mode_selected) {
+               /* cancel any attempt for DSP D0I3 */
+               cancel_delayed_work_sync(&hda->d0i3_work);
+       }
 
        /* stop hda controller and power dsp off */
        ret = hda_suspend(sdev, true);
@@ -866,8 +897,10 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state)
        };
        int ret;
 
-       /* cancel any attempt for DSP D0I3 */
-       cancel_delayed_work_sync(&hda->d0i3_work);
+       if (!sdev->dspless_mode_selected) {
+               /* cancel any attempt for DSP D0I3 */
+               cancel_delayed_work_sync(&hda->d0i3_work);
+       }
 
        if (target_state == SOF_DSP_PM_D0) {
                /* Set DSP power state */
@@ -880,11 +913,9 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state)
                }
 
                /* enable L1SEN to make sure the system can enter S0Ix */
-               hda->l1_support_changed =
-                       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 (hda->l1_disabled)
+                       snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, HDA_VS_INTEL_EM2,
+                                               HDA_VS_INTEL_EM2_L1SEN, HDA_VS_INTEL_EM2_L1SEN);
 
                /* stop the CORB/RIRB DMA if it is On */
                hda_codec_suspend_cmd_io(sdev);