#include <sound/hdaudio_ext.h>
 #include <sound/hda_register.h>
 
+#include <linux/acpi.h>
 #include <linux/module.h>
+#include <linux/soundwire/sdw_intel.h>
 #include <sound/intel-nhlt.h>
 #include <sound/sof.h>
 #include <sound/sof/xtensa.h>
 
 #define EXCEPT_MAX_HDR_SIZE    0x400
 
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
+
+void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable)
+{
+       sdw_intel_enable_irq(sdev->bar[HDA_DSP_BAR], enable);
+}
+
+static int hda_sdw_acpi_scan(struct snd_sof_dev *sdev)
+{
+       struct sof_intel_hda_dev *hdev;
+       acpi_handle handle;
+       int ret;
+
+       handle = ACPI_HANDLE(sdev->dev);
+
+       /* save ACPI info for the probe step */
+       hdev = sdev->pdata->hw_pdata;
+
+       ret = sdw_intel_acpi_scan(handle, &hdev->info);
+       if (ret < 0) {
+               dev_err(sdev->dev, "%s failed\n", __func__);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int hda_sdw_probe(struct snd_sof_dev *sdev)
+{
+       struct sof_intel_hda_dev *hdev;
+       struct sdw_intel_res res;
+       acpi_handle handle;
+       void *sdw;
+
+       handle = ACPI_HANDLE(sdev->dev);
+
+       hdev = sdev->pdata->hw_pdata;
+
+       memset(&res, 0, sizeof(res));
+
+       res.mmio_base = sdev->bar[HDA_DSP_BAR];
+       res.irq = sdev->ipc_irq;
+       res.handle = hdev->info.handle;
+       res.parent = sdev->dev;
+
+       /*
+        * ops and arg fields are not populated for now,
+        * they will be needed when the DAI callbacks are
+        * provided
+        */
+
+       /* we could filter links here if needed, e.g for quirks */
+       res.count = hdev->info.count;
+       res.link_mask = hdev->info.link_mask;
+
+       sdw = sdw_intel_probe(&res);
+       if (!sdw) {
+               dev_err(sdev->dev, "error: SoundWire probe failed\n");
+               return -EINVAL;
+       }
+
+       /* save context */
+       hdev->sdw = sdw;
+
+       return 0;
+}
+
+int hda_sdw_startup(struct snd_sof_dev *sdev)
+{
+       struct sof_intel_hda_dev *hdev;
+
+       hdev = sdev->pdata->hw_pdata;
+
+       return sdw_intel_startup(hdev->sdw);
+}
+
+static int hda_sdw_exit(struct snd_sof_dev *sdev)
+{
+       struct sof_intel_hda_dev *hdev;
+
+       hdev = sdev->pdata->hw_pdata;
+
+       hda_sdw_int_enable(sdev, false);
+
+       if (hdev->sdw)
+               sdw_intel_exit(hdev->sdw);
+       hdev->sdw = NULL;
+
+       return 0;
+}
+#endif
+
 /*
  * Debug
  */
 static int hda_init_caps(struct snd_sof_dev *sdev)
 {
        struct hdac_bus *bus = sof_to_bus(sdev);
+       struct snd_sof_pdata *pdata = sdev->pdata;
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
        struct hdac_ext_link *hlink;
 #endif
+       struct sof_intel_hda_dev *hdev = pdata->hw_pdata;
+       u32 link_mask;
        int ret = 0;
 
        device_disable_async_suspend(bus->dev);
                return ret;
        }
 
+       /* scan SoundWire capabilities exposed by DSDT */
+       ret = hda_sdw_acpi_scan(sdev);
+       if (ret < 0) {
+               dev_err(sdev->dev, "error: SoundWire ACPI scan error\n");
+               return ret;
+       }
+
+       link_mask = hdev->info.link_mask;
+       if (!link_mask) {
+               /*
+                * probe/allocated SoundWire resources.
+                * The hardware configuration takes place in hda_sdw_startup
+                * after power rails are enabled.
+                */
+               ret = hda_sdw_probe(sdev);
+               if (ret < 0) {
+                       dev_err(sdev->dev, "error: SoundWire probe error\n");
+                       return ret;
+               }
+       }
+
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
        if (bus->mlcap)
                snd_hdac_ext_bus_get_ml_capabilities(bus);
        snd_hdac_ext_bus_device_remove(bus);
 #endif
 
+       hda_sdw_exit(sdev);
+
        if (!IS_ERR_OR_NULL(hda->dmic_dev))
                platform_device_unregister(hda->dmic_dev);
 
 
 #ifndef __SOF_INTEL_HDA_H
 #define __SOF_INTEL_HDA_H
 
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_intel.h>
 #include <sound/compress_driver.h>
 #include <sound/hda_codec.h>
 #include <sound/hdaudio_ext.h>
 
        /* delayed work to enter D0I3 opportunistically */
        struct delayed_work d0i3_work;
+
+       /* ACPI information stored between scan and probe steps */
+       struct sdw_intel_acpi_info info;
+
+       /* sdw context allocated by SoundWire driver */
+       struct sdw_intel_ctx *sdw;
 };
 
 static inline struct hdac_bus *sof_to_bus(struct snd_sof_dev *s)
 int hda_dsp_trace_release(struct snd_sof_dev *sdev);
 int hda_dsp_trace_trigger(struct snd_sof_dev *sdev, int cmd);
 
+/*
+ * SoundWire support
+ */
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
+
+int hda_sdw_startup(struct snd_sof_dev *sdev);
+void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable);
+
+#else
+
+static inline int hda_sdw_acpi_scan(struct snd_sof_dev *sdev)
+{
+       return 0;
+}
+
+static inline int hda_sdw_probe(struct snd_sof_dev *sdev)
+{
+       return 0;
+}
+
+static inline int hda_sdw_startup(struct snd_sof_dev *sdev)
+{
+       return 0;
+}
+
+static inline int hda_sdw_exit(struct snd_sof_dev *sdev)
+{
+       return 0;
+}
+
+static inline void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable)
+{
+}
+
+#endif
+
 /* common dai driver */
 extern struct snd_soc_dai_driver skl_dai[];