mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Cezary Rojewski <cezary.rojewski@intel.com>
To: linux-sound@vger.kernel.org
Cc: broonie@kernel.org, tiwai@suse.com, perex@perex.cz,
	amade@asmblr.net, linux-kernel@vger.kernel.org,
	pierre-louis.bossart@linux.dev, vkoul@kernel.org,
	yung-chuan.liao@linux.intel.com,
	Cezary Rojewski <cezary.rojewski@intel.com>
Subject: [PATCH v2 5/7] ASoC: Intel: avs: SoundWire support
Date: Tue,  3 Nov 2026 14:49:56 +0100	[thread overview]
Message-ID: <20261103134958.2089136-6-cezary.rojewski@intel.com> (raw)
In-Reply-To: <20261103134958.2089136-1-cezary.rojewski@intel.com>

The SoundWire device is part of the Intel HDAudio PCI device. To support
transfer over SoundWire interface it has to be accounted for when
probing the parent device.

Most of the actual job is done by the SoundWire library which is already
part of the kernel. Utilize it in the core functions of the driver to
enumerate SoundWire component and service its interrupts.

Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
 sound/soc/intel/Kconfig         |   8 +++
 sound/soc/intel/avs/Makefile    |   4 ++
 sound/soc/intel/avs/avs.h       |   1 +
 sound/soc/intel/avs/cnl.c       |  23 ++++++-
 sound/soc/intel/avs/core.c      |  20 ++++++
 sound/soc/intel/avs/loader.c    |   3 +
 sound/soc/intel/avs/registers.h |   4 ++
 sound/soc/intel/avs/soundwire.c | 117 ++++++++++++++++++++++++++++++++
 sound/soc/intel/avs/soundwire.h |  56 +++++++++++++++
 9 files changed, 234 insertions(+), 2 deletions(-)
 create mode 100644 sound/soc/intel/avs/soundwire.c
 create mode 100644 sound/soc/intel/avs/soundwire.h

diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index 63367364916a..c765eee25763 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -106,12 +106,20 @@ config SND_SOC_INTEL_AVS
 	select SND_HDA_EXT_CORE
 	select SND_HDA_DSP_LOADER
 	select SND_INTEL_DSP_CONFIG
+	select SND_INTEL_SOUNDWIRE_ACPI if SOUNDWIRE_INTEL != n
 	select WANT_DEV_COREDUMP
 	help
 	  Enable support for Intel(R) cAVS 1.5 platforms with DSP
 	  capabilities. This includes Skylake, Kabylake, Amberlake and
 	  Apollolake.
 
+config SND_SOC_INTEL_AVS_SOUNDWIRE
+	tristate
+	default SND_SOC_INTEL_AVS
+	depends on SND_SOC_INTEL_AVS
+	depends on SOUNDWIRE_INTEL
+	depends on !(SOUNDWIRE_INTEL=m && SND_SOC_INTEL_AVS=y)
+
 # Machine board drivers
 source "sound/soc/intel/avs/boards/Kconfig"
 
diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile
index 576dc0da381d..042e8dd232f8 100644
--- a/sound/soc/intel/avs/Makefile
+++ b/sound/soc/intel/avs/Makefile
@@ -14,6 +14,10 @@ ifneq ($(CONFIG_DEBUG_FS),)
 snd-soc-avs-y += probes.o debugfs.o
 endif
 
+ifneq ($(CONFIG_SND_SOC_INTEL_AVS_SOUNDWIRE),)
+snd-soc-avs-y += soundwire.o
+endif
+
 obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o
 
 # Machine support
diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h
index b3af2c4126be..40e65639adb2 100644
--- a/sound/soc/intel/avs/avs.h
+++ b/sound/soc/intel/avs/avs.h
@@ -136,6 +136,7 @@ struct avs_dev {
 	void __iomem *dsp_ba;
 	const struct avs_spec *spec;
 	struct avs_ipc *ipc;
+	struct sdw_intel_ctx *sdw;
 
 	struct avs_fw_cfg fw_cfg;
 	struct avs_hw_cfg hw_cfg;
diff --git a/sound/soc/intel/avs/cnl.c b/sound/soc/intel/avs/cnl.c
index 31fd9f251d6c..7090b91572d8 100644
--- a/sound/soc/intel/avs/cnl.c
+++ b/sound/soc/intel/avs/cnl.c
@@ -6,11 +6,16 @@
 //          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
 //
 
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_intel.h>
 #include <sound/hdaudio_ext.h>
 #include "avs.h"
 #include "debug.h"
 #include "messages.h"
 #include "registers.h"
+#include "soundwire.h"
 
 static void avs_cnl_ipc_interrupt(struct avs_dev *adev)
 {
@@ -61,16 +66,30 @@ static void avs_cnl_ipc_interrupt(struct avs_dev *adev)
 irqreturn_t avs_cnl_dsp_interrupt(struct avs_dev *adev, int irq)
 {
 	u32 adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS);
+	u32 adspis2 = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS2);
 	irqreturn_t ret = IRQ_NONE;
 
-	if (adspis == UINT_MAX)
+	if (adspis == UINT_MAX && adspis2 == UINT_MAX)
 		return ret;
 
-	if (adspis & AVS_ADSP_ADSPIS_IPC) {
+	if (adspis != UINT_MAX && (adspis & AVS_ADSP_ADSPIS_IPC)) {
 		avs_cnl_ipc_interrupt(adev);
 		ret = IRQ_HANDLED;
 	}
 
+	if (adev->sdw) {
+		u32 wakests;
+
+		if (adspis2 != UINT_MAX && (adspis2 & AVS_ADSP_ADSPIS2_SNDW))
+			ret = avs_sdw_thread(irq, adev);
+
+		wakests = snd_hdac_adsp_readl(adev, adev->sdw->shim_base + SDW_SHIM_WAKESTS);
+		if (wakests) {
+			avs_sdw_process_wakeen_event(adev);
+			ret = IRQ_HANDLED;
+		}
+	}
+
 	return ret;
 }
 
diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c
index 9413027e1e32..3cabe9a2d104 100644
--- a/sound/soc/intel/avs/core.c
+++ b/sound/soc/intel/avs/core.c
@@ -31,6 +31,7 @@
 #include "debug.h"
 #include "messages.h"
 #include "pcm.h"
+#include "soundwire.h"
 
 static u32 pgctl_mask = AZX_PGCTL_LSRMD_MASK;
 module_param(pgctl_mask, uint, 0444);
@@ -230,6 +231,11 @@ static void avs_hda_probe_work(struct work_struct *work)
 	list_for_each_entry(hlink, &bus->hlink_list, list)
 		snd_hdac_ext_bus_link_put(bus, hlink);
 
+	/* Soundwire component is optional */
+	ret = avs_sdw_probe(adev);
+	if (ret && ret != -ENODEV)
+		dev_err(adev->dev, "failed to probe sdw: %d\n", ret);
+
 	snd_hdac_ext_bus_ppcap_enable(bus, true);
 	snd_hdac_ext_bus_ppcap_int_enable(bus, true);
 	avs_debugfs_init(adev);
@@ -240,6 +246,14 @@ static void avs_hda_probe_work(struct work_struct *work)
 
 	acpi_nhlt_get_gbl_table();
 
+	ret = avs_sdw_startup(adev);
+	if (ret) {
+		dev_err(adev->dev, "failed to startup sdw: %d\n", ret);
+		return;
+	}
+
+	avs_sdw_enable_irq(adev, true);
+
 	avs_register_all_boards(adev);
 
 	/* configure PM */
@@ -561,6 +575,8 @@ static void avs_pci_shutdown(struct pci_dev *pci)
 	snd_hdac_bus_stop_chip(bus);
 	snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
 
+	avs_sdw_enable_irq(adev, false);
+
 	pci_free_irq(pci, 0, adev);
 	pci_free_irq(pci, 0, bus);
 	pci_free_irq_vectors(pci);
@@ -579,6 +595,7 @@ static void avs_pci_remove(struct pci_dev *pci)
 
 	acpi_nhlt_put_gbl_table();
 	avs_debugfs_exit(adev);
+	avs_sdw_exit(adev);
 
 	if (avs_platattr_test(adev, CLDMA))
 		hda_cldma_free(&code_loader);
@@ -661,6 +678,7 @@ static int avs_suspend_common(struct avs_dev *adev, bool low_power)
 	}
 
 	avs_ipc_block(adev->ipc);
+	avs_sdw_enable_irq(adev, false);
 	avs_dsp_op(adev, int_control, false);
 	snd_hdac_ext_bus_ppcap_int_enable(bus, false);
 
@@ -720,6 +738,8 @@ static int avs_resume_common(struct avs_dev *adev, bool low_power, bool purge)
 		return ret;
 	}
 
+	avs_sdw_enable_irq(adev, true);
+
 	return 0;
 }
 
diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c
index bebdc79ec88e..27d09a3bb5ef 100644
--- a/sound/soc/intel/avs/loader.c
+++ b/sound/soc/intel/avs/loader.c
@@ -18,6 +18,7 @@
 #include "messages.h"
 #include "registers.h"
 #include "topology.h"
+#include "soundwire.h"
 
 #define AVS_ROM_STS_MASK		0xFF
 #define AVS_ROM_INIT_DONE		0x1
@@ -345,6 +346,8 @@ static int avs_imr_load_basefw(struct avs_dev *adev)
 	if (ret < 0)
 		return ret;
 
+	avs_sdw_process_wakeen_event(adev);
+
 	ret = wait_for_completion_timeout(&adev->fw_ready,
 					  msecs_to_jiffies(AVS_FW_INIT_TIMEOUT_MS));
 	if (!ret) {
diff --git a/sound/soc/intel/avs/registers.h b/sound/soc/intel/avs/registers.h
index 97767882ffa1..9e403cfb04fa 100644
--- a/sound/soc/intel/avs/registers.h
+++ b/sound/soc/intel/avs/registers.h
@@ -25,11 +25,15 @@
 #define AVS_ADSP_REG_ADSPCS		(AVS_ADSP_GEN_BASE + 0x04)
 #define AVS_ADSP_REG_ADSPIC		(AVS_ADSP_GEN_BASE + 0x08)
 #define AVS_ADSP_REG_ADSPIS		(AVS_ADSP_GEN_BASE + 0x0C)
+#define AVS_ADSP_REG_ADSPIC2		(AVS_ADSP_GEN_BASE + 0x10)
+#define AVS_ADSP_REG_ADSPIS2		(AVS_ADSP_GEN_BASE + 0x14)
 
 #define AVS_ADSP_ADSPIC_IPC		BIT(0)
 #define AVS_ADSP_ADSPIC_CLDMA		BIT(1)
 #define AVS_ADSP_ADSPIS_IPC		BIT(0)
 #define AVS_ADSP_ADSPIS_CLDMA		BIT(1)
+#define AVS_ADSP_ADSPIC2_SNDW		BIT(5)
+#define AVS_ADSP_ADSPIS2_SNDW		BIT(5)
 
 #define AVS_ADSPCS_CRST_MASK(cm)	(cm)
 #define AVS_ADSPCS_CSTALL_MASK(cm)	((cm) << 8)
diff --git a/sound/soc/intel/avs/soundwire.c b/sound/soc/intel/avs/soundwire.c
new file mode 100644
index 000000000000..284a00ea794e
--- /dev/null
+++ b/sound/soc/intel/avs/soundwire.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright(c) 2021-2026 Intel Corporation
+//
+// Authors: Cezary Rojewski <cezary.rojewski@intel.com>
+//          Amadeusz Slawinski <amade@asmblr.net>
+//
+
+#include <linux/acpi.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_intel.h>
+#include <sound/hdaudio_ext.h>
+#include "avs.h"
+#include "registers.h"
+#include "soundwire.h"
+
+static struct sdw_intel_hw_ops avs_sdw_cnl_ops;
+
+int avs_sdw_probe(struct avs_dev *adev)
+{
+	struct hdac_bus *hbus = &adev->base.core;
+	struct sdw_intel_acpi_info info;
+	struct sdw_intel_ctx *ctx;
+	struct sdw_intel_res res;
+	int ret;
+
+	if (avs_platattr_test(adev, ALTHDA))
+		return -ENODEV;
+
+	ret = sdw_intel_acpi_scan(ACPI_HANDLE(adev->dev), &info);
+	if (ret || !info.link_mask)
+		return ret;
+
+	memset(&res, 0, sizeof(res));
+	res.mmio_base = adev->dsp_ba;
+	res.shim_base = SDW_SHIM_BASE;
+	res.alh_base = SDW_ALH_BASE;
+	res.ext = false;
+	res.irq = adev->base.core.irq;
+	res.handle = info.handle;
+	res.parent = adev->dev;
+	res.dev = adev->dev;
+	res.clock_stop_quirks = SDW_INTEL_CLK_STOP_BUS_RESET;
+	res.hbus = hbus;
+
+	memcpy(&avs_sdw_cnl_ops, &sdw_intel_cnl_hw_ops, sizeof(avs_sdw_cnl_ops));
+	avs_sdw_cnl_ops.register_dai = NULL;
+	res.hw_ops = &avs_sdw_cnl_ops;
+
+	/* we could filter links here if needed, e.g.: for quirks */
+	res.count = info.count;
+	res.link_mask = info.link_mask;
+
+	ctx = sdw_intel_probe(&res);
+	if (!ctx) {
+		dev_err(adev->dev, "SoundWire probe failed\n");
+		return -EINVAL;
+	}
+
+	adev->sdw = ctx;
+	return 0;
+}
+
+int avs_sdw_startup(struct avs_dev *adev)
+{
+	if (adev->sdw)
+		return sdw_intel_startup(adev->sdw);
+	return 0;
+}
+
+void avs_sdw_exit(struct avs_dev *adev)
+{
+	struct sdw_intel_ctx *ctx = adev->sdw;
+
+	if (ctx) {
+		adev->sdw = NULL;
+		sdw_intel_exit(ctx);
+	}
+}
+
+// TODO split tgl vs mtl
+static void sdw_intel_enable_irq(void __iomem *mmio_base, bool enable)
+{
+	u32 val;
+
+	val = readl(mmio_base + AVS_ADSP_REG_ADSPIC2);
+
+	if (enable)
+		val |= AVS_ADSP_ADSPIC2_SNDW;
+	else
+		val &= ~AVS_ADSP_ADSPIC2_SNDW;
+
+	writel(val, mmio_base + AVS_ADSP_REG_ADSPIC2);
+}
+
+void avs_sdw_enable_irq(struct avs_dev *adev, bool enable)
+{
+	if (adev->sdw)
+		sdw_intel_enable_irq(adev->dsp_ba, enable);
+}
+
+void avs_sdw_process_wakeen_event(struct avs_dev *adev)
+{
+	if (adev->sdw)
+		sdw_intel_process_wakeen_event(adev->sdw);
+}
+
+irqreturn_t avs_sdw_thread(int irq, struct avs_dev *adev)
+{
+	if (adev->sdw)
+		return sdw_intel_thread(irq, adev->sdw);
+	return IRQ_HANDLED;
+}
+
+MODULE_IMPORT_NS("SOUNDWIRE_INTEL");
+MODULE_IMPORT_NS("SOUNDWIRE_INTEL_INIT");
+MODULE_IMPORT_NS("SND_INTEL_SOUNDWIRE_ACPI");
diff --git a/sound/soc/intel/avs/soundwire.h b/sound/soc/intel/avs/soundwire.h
new file mode 100644
index 000000000000..e57e29ed16bf
--- /dev/null
+++ b/sound/soc/intel/avs/soundwire.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright(c) 2021-2026 Intel Corporation
+ *
+ * Authors: Cezary Rojewski <cezary.rojewski@intel.com>
+ *          Amadeusz Slawinski <amade@asmblr.net>
+ */
+
+#ifndef __SOUND_SOC_INTEL_AVS_SOUNDWIRE_H
+#define __SOUND_SOC_INTEL_AVS_SOUNDWIRE_H
+
+#include <linux/irqreturn.h>
+
+struct avs_dev;
+
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_AVS_SOUNDWIRE)
+
+int avs_sdw_probe(struct avs_dev *adev);
+int avs_sdw_startup(struct avs_dev *adev);
+void avs_sdw_exit(struct avs_dev *adev);
+void avs_sdw_enable_irq(struct avs_dev *adev, bool enable);
+void avs_sdw_process_wakeen_event(struct avs_dev *adev);
+irqreturn_t avs_sdw_thread(int irq, struct avs_dev *adev);
+
+#else
+
+static inline int avs_sdw_probe(struct avs_dev *adev)
+{
+	return 0;
+}
+
+static inline int avs_sdw_startup(struct avs_dev *adev)
+{
+	return 0;
+}
+
+static inline void avs_sdw_exit(struct avs_dev *adev)
+{
+}
+
+static inline void avs_sdw_enable_irq(struct avs_dev *adev, bool enable)
+{
+}
+
+static inline void avs_sdw_process_wakeen_event(struct avs_dev *adev)
+{
+}
+
+static inline irqreturn_t avs_sdw_thread(int irq, struct avs_dev *adev)
+{
+	return IRQ_HANDLED;
+}
+
+#endif
+
+#endif /* __SOUND_SOC_INTEL_AVS_SOUNDWIRE_H */
-- 
2.34.1


  parent reply	other threads:[~2026-11-03 13:43 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-03 13:49 [PATCH v2 0/7] ASoC: Intel: avs: Soundwire support Cezary Rojewski
2026-11-03 13:49 ` [PATCH v2 1/7] soundwire: intel: Define stubs when library is disabled Cezary Rojewski
2026-11-03 13:49 ` [PATCH v2 2/7] soundwire: intel: Allow for dynamic assignment of PDIs Cezary Rojewski
2026-11-03 13:49 ` [PATCH v2 3/7] soundwire: intel: Split PDIs and DAIs initialization Cezary Rojewski
2026-11-03 13:49 ` [PATCH v2 4/7] ASoC: Intel: avs: Pass irq to dsp_interrupt callback Cezary Rojewski
2026-11-03 13:49 ` Cezary Rojewski [this message]
2026-11-03 13:49 ` [PATCH v2 6/7] ASoC: Intel: avs: Expose common PCM functions Cezary Rojewski
2026-11-03 13:49 ` [PATCH v2 7/7] ASoC: Intel: avs: SoundWire PCM BE operations Cezary Rojewski
2026-11-03 17:20 ` [PATCH v2 0/7] ASoC: Intel: avs: Soundwire support Pierre-Louis Bossart

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261103134958.2089136-6-cezary.rojewski@intel.com \
    --to=cezary.rojewski@intel.com \
    --cc=amade@asmblr.net \
    --cc=broonie@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=pierre-louis.bossart@linux.dev \
    --cc=tiwai@suse.com \
    --cc=vkoul@kernel.org \
    --cc=yung-chuan.liao@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®