pm_runtime_get_noresume(&pci->dev);
 }
 
-static int __maybe_unused avs_suspend_common(struct avs_dev *adev)
+static int avs_suspend_standby(struct avs_dev *adev)
+{
+       struct hdac_bus *bus = &adev->base.core;
+       struct pci_dev *pci = adev->base.pci;
+
+       if (bus->cmd_dma_state)
+               snd_hdac_bus_stop_cmd_io(bus);
+
+       snd_hdac_ext_bus_link_power_down_all(bus);
+
+       enable_irq_wake(pci->irq);
+       pci_save_state(pci);
+
+       return 0;
+}
+
+static int __maybe_unused avs_suspend_common(struct avs_dev *adev, bool low_power)
 {
        struct hdac_bus *bus = &adev->base.core;
        int ret;
 
        flush_work(&adev->probe_work);
+       if (low_power && adev->num_lp_paths)
+               return avs_suspend_standby(adev);
 
        snd_hdac_ext_bus_link_power_down_all(bus);
 
        return 0;
 }
 
-static int __maybe_unused avs_resume_common(struct avs_dev *adev, bool purge)
+static int avs_resume_standby(struct avs_dev *adev)
+{
+       struct hdac_bus *bus = &adev->base.core;
+       struct pci_dev *pci = adev->base.pci;
+
+       pci_restore_state(pci);
+       disable_irq_wake(pci->irq);
+
+       snd_hdac_ext_bus_link_power_up_all(bus);
+
+       if (bus->cmd_dma_state)
+               snd_hdac_bus_init_cmd_io(bus);
+
+       return 0;
+}
+
+static int __maybe_unused avs_resume_common(struct avs_dev *adev, bool low_power, bool purge)
 {
        struct hdac_bus *bus = &adev->base.core;
        int ret;
 
+       if (low_power && adev->num_lp_paths)
+               return avs_resume_standby(adev);
+
        snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
        avs_hdac_bus_init_chip(bus, true);
 
 
 static int __maybe_unused avs_suspend(struct device *dev)
 {
-       return avs_suspend_common(to_avs_dev(dev));
+       return avs_suspend_common(to_avs_dev(dev), true);
 }
 
 static int __maybe_unused avs_resume(struct device *dev)
 {
-       return avs_resume_common(to_avs_dev(dev), true);
+       return avs_resume_common(to_avs_dev(dev), true, true);
 }
 
 static int __maybe_unused avs_runtime_suspend(struct device *dev)
 {
-       return avs_suspend_common(to_avs_dev(dev));
+       return avs_suspend_common(to_avs_dev(dev), true);
 }
 
 static int __maybe_unused avs_runtime_resume(struct device *dev)
 {
-       return avs_resume_common(to_avs_dev(dev), true);
+       return avs_resume_common(to_avs_dev(dev), true, false);
+}
+
+static int __maybe_unused avs_freeze(struct device *dev)
+{
+       return avs_suspend_common(to_avs_dev(dev), false);
+}
+static int __maybe_unused avs_thaw(struct device *dev)
+{
+       return avs_resume_common(to_avs_dev(dev), false, true);
+}
+
+static int __maybe_unused avs_poweroff(struct device *dev)
+{
+       return avs_suspend_common(to_avs_dev(dev), false);
+}
+
+static int __maybe_unused avs_restore(struct device *dev)
+{
+       return avs_resume_common(to_avs_dev(dev), false, true);
 }
 
 static const struct dev_pm_ops avs_dev_pm = {
-       SET_SYSTEM_SLEEP_PM_OPS(avs_suspend, avs_resume)
+       .suspend = avs_suspend,
+       .resume = avs_resume,
+       .freeze = avs_freeze,
+       .thaw = avs_thaw,
+       .poweroff = avs_poweroff,
+       .restore = avs_restore,
        SET_RUNTIME_PM_OPS(avs_runtime_suspend, avs_runtime_resume, NULL)
 };
 
 
        if (!le32_to_cpu(dw->priv.size))
                return 0;
 
+       if (w->ignore_suspend && !AVS_S0IX_SUPPORTED) {
+               dev_info_once(comp->dev, "Device does not support S0IX, check BIOS settings\n");
+               w->ignore_suspend = false;
+       }
+
        tplg = acomp->tplg;
        mach = dev_get_platdata(comp->card->dev);
 
 static int avs_link_load(struct snd_soc_component *comp, int index, struct snd_soc_dai_link *link,
                         struct snd_soc_tplg_link_config *cfg)
 {
+       if (link->ignore_suspend && !AVS_S0IX_SUPPORTED) {
+               dev_info_once(comp->dev, "Device does not support S0IX, check BIOS settings\n");
+               link->ignore_suspend = false;
+       }
+
        if (!link->no_pcm) {
                /* Stream control handled by IPCs. */
                link->nonatomic = true;