mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/7] ASoC: Intel: avs: Soundwire support
@ 2026-11-02 18:10 Cezary Rojewski
  2026-11-02 18:10 ` [PATCH 1/7] soundwire: intel: Define stubs when library is disabled Cezary Rojewski
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Cezary Rojewski @ 2026-11-02 18:10 UTC (permalink / raw)
  To: linux-sound
  Cc: broonie, tiwai, perex, amade, linux-kernel, yung-chuan.liao,
	pierre-louis.bossart, vkoul, Cezary Rojewski

The RaptorLake-P and RaptorLake-M based platform used in Automotive area
do utilize SoundWire for streaming audio.  This patchset brings such
support to the public domain.

If possible, I'd like the changes to go through Mark's tree.

As the patchset updates drivers/soundwire, I've decided to strip it off
any machine-boards and have here just the changes done to the main
soundwire driver and their user/usage.  Machine boards for RPL-P/M will
follow in a separate set and do not touch drivers/soundwire stuff.


The reasoning behind modyfing the soundwire code:

Typically dai->startup() is responsible for checking if all the required
resources are available whereas dai->hw_params() is responsible for
configuring such resources.  Existing code does the PDI assignment and
its configuration within one function - intel_hw_params().  The logical
split is not possible.  The change provides functions that represent
such logical blocks: assign, release and config.  Such division exists
already for the HDAudio interface, see sound/hda/core/stream.c

For the user i.e.: avs-driver (sound/soc/intel/avs) it also makes the
code very cohesive - aligns with that's done on the HDAudio side as all
the HDAudio streams are assignment during dai->startup() and configured
with dai->hw_params().  

Also, the existing code fetches the PDIs based on pre-defined "dai_id".
That's not the case for the avs-driver.  It simply asks: "is any PDI
free?" and assigns it for the substream if one is found.
No predefining.  Again, this aligns with how HDAudio streaming is done.

avs-driver -only patches follow the three soundwire ones.  First, they
extend the existing code so it can accommodate SDW interface.  With that
done, laverage existing PCM code (sound/soc/intel/avs/pcm.c) and
soundwire-intel to implement DAI operations.

Cezary Rojewski (7):
  soundwire: intel: Define stubs when library is disabled
  soundwire: intel: Allow for dynamic assignment of PDIs
  soundwire: intel: Split PDIs and DAIs initialization
  ASoC: Intel: avs: Pass irq to dsp_interrupt callback
  ASoC: Intel: avs: SoundWire support
  ASoC: Intel: avs: Expose common PCM functions
  ASoC: Intel: avs: SoundWire PCM BE operations

 drivers/soundwire/cadence_master.c    |  64 ++++++
 drivers/soundwire/cadence_master.h    |  24 +--
 drivers/soundwire/intel.c             |  40 +++-
 drivers/soundwire/intel.h             |   3 +-
 drivers/soundwire/intel_auxdevice.c   |   4 +
 include/linux/soundwire/sdw_cadence.h |  35 ++++
 include/linux/soundwire/sdw_intel.h   |  41 ++++
 sound/hda/core/Kconfig                |   2 +-
 sound/hda/core/Makefile               |   3 +
 sound/soc/intel/Kconfig               |   1 +
 sound/soc/intel/avs/Makefile          |   4 +
 sound/soc/intel/avs/apl.c             |   2 +-
 sound/soc/intel/avs/avs.h             |  15 +-
 sound/soc/intel/avs/cnl.c             |  25 ++-
 sound/soc/intel/avs/core.c            |  24 ++-
 sound/soc/intel/avs/loader.c          |   3 +
 sound/soc/intel/avs/messages.h        |   2 +
 sound/soc/intel/avs/mtl.c             |   2 +-
 sound/soc/intel/avs/path.c            |   2 +
 sound/soc/intel/avs/pcm.c             |  42 +---
 sound/soc/intel/avs/pcm.h             |  51 +++++
 sound/soc/intel/avs/pcm_sdw.c         | 276 ++++++++++++++++++++++++++
 sound/soc/intel/avs/registers.h       |   4 +
 sound/soc/intel/avs/skl.c             |   2 +-
 sound/soc/intel/avs/soundwire.c       | 112 +++++++++++
 sound/soc/intel/avs/soundwire.h       |  63 ++++++
 26 files changed, 765 insertions(+), 81 deletions(-)
 create mode 100644 include/linux/soundwire/sdw_cadence.h
 create mode 100644 sound/soc/intel/avs/pcm_sdw.c
 create mode 100644 sound/soc/intel/avs/soundwire.c
 create mode 100644 sound/soc/intel/avs/soundwire.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/7] soundwire: intel: Define stubs when library is disabled
  2026-11-02 18:10 [PATCH 0/7] ASoC: Intel: avs: Soundwire support Cezary Rojewski
@ 2026-11-02 18:10 ` Cezary Rojewski
  2026-11-02 18:10 ` [PATCH 2/7] soundwire: intel: Allow for dynamic assignment of PDIs Cezary Rojewski
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Cezary Rojewski @ 2026-11-02 18:10 UTC (permalink / raw)
  To: linux-sound
  Cc: broonie, tiwai, perex, amade, linux-kernel, yung-chuan.liao,
	pierre-louis.bossart, vkoul, Cezary Rojewski

The library defines no stubs when it is disabled so the actual users
have to do it locally to allow the code to compilte or, guard the code
that does interact with soundwire with #if(s). Define simple wrappers to
make the life of soundwire-code users easier.

The change allows for a driver to build against SOUNDWIRE_INTEL=n whilst
still calling the stubs in its common code without compilation failing.
The driver needs not to flank its soundwire-code with #if(s) either.

Not all sdw_intel_xxx()s are part of drivers/soundwire. Some definitions
are located within sound/hda/core instead. With the wrappers done,
update Kconfig for sound/hda/core as currently the ACPI-related function
are compiled regardless if SOUNDWIRE_INTEL is selected or not. By being
dependent on SOUNDWIRE_INTEL those functions are compiled only if the
SoundWire was actually requested.

Cc: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
 include/linux/soundwire/sdw_intel.h | 34 +++++++++++++++++++++++++++++
 sound/hda/core/Kconfig              |  2 +-
 sound/hda/core/Makefile             |  3 +++
 3 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h
index 9710f2dc04e2..83021cc0f5b8 100644
--- a/include/linux/soundwire/sdw_intel.h
+++ b/include/linux/soundwire/sdw_intel.h
@@ -358,6 +358,8 @@ struct sdw_intel_res {
 	struct mutex *eml_lock;
 };
 
+#if IS_ENABLED(CONFIG_SOUNDWIRE_INTEL)
+
 /*
  * On Intel platforms, the SoundWire IP has dependencies on power
  * rails shared with the DSP, and the initialization steps are split
@@ -384,6 +386,38 @@ void sdw_intel_exit(struct sdw_intel_ctx *ctx);
 
 irqreturn_t sdw_intel_thread(int irq, void *dev_id);
 
+#else
+
+static inline int sdw_intel_acpi_scan(acpi_handle parent_handle, struct sdw_intel_acpi_info *info)
+{
+	return 0;
+}
+
+static inline void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx)
+{
+}
+
+static inline struct sdw_intel_ctx *sdw_intel_probe(struct sdw_intel_res *res)
+{
+	return NULL;
+}
+
+static inline int sdw_intel_startup(struct sdw_intel_ctx *ctx)
+{
+	return 0;
+}
+
+static inline void sdw_intel_exit(struct sdw_intel_ctx *ctx)
+{
+}
+
+static inline irqreturn_t sdw_intel_thread(int irq, void *dev_id)
+{
+	return 0;
+}
+
+#endif
+
 #define SDW_INTEL_QUIRK_MASK_BUS_DISABLE      BIT(1)
 
 struct sdw_intel;
diff --git a/sound/hda/core/Kconfig b/sound/hda/core/Kconfig
index bfdcf6384c52..f91053dd9f58 100644
--- a/sound/hda/core/Kconfig
+++ b/sound/hda/core/Kconfig
@@ -29,7 +29,7 @@ config SND_INTEL_DSP_CONFIG
 	tristate
 	select ACPI_NHLT if ACPI
 	select SND_INTEL_NHLT if ACPI
-	select SND_INTEL_SOUNDWIRE_ACPI if ACPI
+	select SND_INTEL_SOUNDWIRE_ACPI if SOUNDWIRE_INTEL
 	# this config should be selected only for Intel DSP platforms.
 	# A fallback is provided so that the code compiles in all cases.
 
diff --git a/sound/hda/core/Makefile b/sound/hda/core/Makefile
index 89cb46143050..28032ac7bc61 100644
--- a/sound/hda/core/Makefile
+++ b/sound/hda/core/Makefile
@@ -18,5 +18,8 @@ snd-intel-dspcfg-y := intel-dsp-config.o
 snd-intel-dspcfg-$(CONFIG_SND_INTEL_NHLT) += intel-nhlt.o
 obj-$(CONFIG_SND_INTEL_DSP_CONFIG) += snd-intel-dspcfg.o
 
+ifneq ($(CONFIG_SND_INTEL_SOUNDWIRE_ACPI),)
 snd-intel-sdw-acpi-y := intel-sdw-acpi.o
+endif
+
 obj-$(CONFIG_SND_INTEL_SOUNDWIRE_ACPI) += snd-intel-sdw-acpi.o
-- 
2.34.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/7] soundwire: intel: Allow for dynamic assignment of PDIs
  2026-11-02 18:10 [PATCH 0/7] ASoC: Intel: avs: Soundwire support Cezary Rojewski
  2026-11-02 18:10 ` [PATCH 1/7] soundwire: intel: Define stubs when library is disabled Cezary Rojewski
@ 2026-11-02 18:10 ` Cezary Rojewski
  2026-11-02 18:10 ` [PATCH 3/7] soundwire: intel: Split PDIs and DAIs initialization Cezary Rojewski
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Cezary Rojewski @ 2026-11-02 18:10 UTC (permalink / raw)
  To: linux-sound
  Cc: broonie, tiwai, perex, amade, linux-kernel, yung-chuan.liao,
	pierre-louis.bossart, vkoul, Cezary Rojewski

Currently, PDIs are assigned upfront based on the DAI IDs. Some drivers
do not assign anything upfront and request a free PDI when streaming is
about to start.

Provide assign/release() functions to allow them to be assigned
dynamically. This also streamlines the process of assigning/releasing
PDIs with what is done in HDAudio library (sound/hda) for HDAudio
streams, see snd_hdac_stream_assign/release().

As resource availability-check is typically done during dai->startup()
whilst hardware/firmware configuration occurs on dai->hw_params(), add
sdw_intel_pdi_config() to maintain this logical split - assign on
start(), configure on hw_params(). Existing code does all of that in
intel_hw_params() so the logical split is not possible.

Cc: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
 drivers/soundwire/cadence_master.c    | 64 +++++++++++++++++++++++++++
 drivers/soundwire/cadence_master.h    | 24 ++--------
 drivers/soundwire/intel.c             | 16 +++++++
 include/linux/soundwire/sdw_cadence.h | 35 +++++++++++++++
 include/linux/soundwire/sdw_intel.h   |  7 +++
 5 files changed, 125 insertions(+), 21 deletions(-)
 create mode 100644 include/linux/soundwire/sdw_cadence.h

diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c
index a0a63b76793e..9375db9c08a2 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -17,6 +17,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/soundwire/sdw_registers.h>
 #include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_cadence.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <linux/workqueue.h>
@@ -1835,6 +1836,7 @@ int sdw_cdns_probe(struct sdw_cdns *cdns)
 
 	mutex_init(&cdns->status_update_lock);
 
+	spin_lock_init(&cdns->pdi_lock);
 	INIT_WORK(&cdns->work, cdns_update_slave_status_work);
 	INIT_DELAYED_WORK(&cdns->attach_dwork, cdns_check_attached_status_dwork);
 
@@ -1991,6 +1993,68 @@ struct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns,
 }
 EXPORT_SYMBOL(sdw_cdns_alloc_pdi);
 
+/**
+ * sdw_cdns_assign_pdi - Assign a PDI
+ * @bus: SoundWire bus instance
+ * @dir: Data direction
+ *
+ * Return: A valid PDI instance or %NULL if none available.
+ */
+struct sdw_cdns_pdi *sdw_cdns_assign_pdi(struct sdw_bus *bus, u32 dir)
+{
+	struct sdw_cdns *cdns = bus_to_cdns(bus);
+	struct sdw_cdns_streams *stream = &cdns->pcm;
+	struct sdw_cdns_pdi *pdis, *pdi;
+	size_t num_pdis;
+	int i;
+
+	if (dir == SDW_DATA_DIR_RX) {
+		num_pdis = stream->num_in;
+		pdis = stream->in;
+	} else {
+		num_pdis = stream->num_out;
+		pdis = stream->out;
+	}
+
+	spin_lock(&cdns->pdi_lock);
+	for (i = 0; i < num_pdis; i++) {
+		if (!pdis[i].assigned) {
+			pdi = &pdis[i];
+			goto found;
+		}
+	}
+
+	/* Indexes 0/1 are reserved for the Bulk transfer. */
+	for (i = 2; i < stream->num_bd; i++) {
+		if (!stream->bd[i].assigned) {
+			pdi = &stream->bd[i];
+			goto found;
+		}
+	}
+
+	spin_unlock(&cdns->pdi_lock);
+	return NULL;
+found:
+	pdi->dir = dir;
+	pdi->assigned = true;
+	spin_unlock(&cdns->pdi_lock);
+	return pdi;
+}
+EXPORT_SYMBOL(sdw_cdns_assign_pdi);
+
+/**
+ * sdw_cdns_release_pdi() - Release a PDI
+ * @pdi: PDI instance
+ */
+void sdw_cdns_release_pdi(struct sdw_bus *bus, struct sdw_cdns_pdi *pdi)
+{
+	struct sdw_cdns *cdns = bus_to_cdns(bus);
+
+	guard(spinlock)(&cdns->pdi_lock);
+	pdi->assigned = false;
+}
+EXPORT_SYMBOL(sdw_cdns_release_pdi);
+
 /*
  * the MIPI SoundWire CRC8 polynomial is X^8 + X^6 + X^3 + X^2 + 1, MSB first
  * The value is (1)01001101 = 0x4D
diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h
index f4e41a9ab165..f52c9cbec8a9 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -6,6 +6,8 @@
 #ifndef __SDW_CADENCE_H
 #define __SDW_CADENCE_H
 
+#include <linux/soundwire/sdw_cadence.h>
+
 #define SDW_CADENCE_GSYNC_KHZ		4 /* 4 kHz */
 #define SDW_CADENCE_GSYNC_HZ		(SDW_CADENCE_GSYNC_KHZ * 1000)
 
@@ -17,27 +19,6 @@
 
 #define SDW_CADENCE_MCP_IP_OFFSET	0x4000
 
-/**
- * struct sdw_cdns_pdi: PDI (Physical Data Interface) instance
- *
- * @num: pdi number
- * @intel_alh_id: link identifier
- * @l_ch_num: low channel for PDI
- * @h_ch_num: high channel for PDI
- * @ch_count: total channel count for PDI
- * @dir: data direction
- * @type: stream type, (only PCM supported)
- */
-struct sdw_cdns_pdi {
-	int num;
-	int intel_alh_id;
-	int l_ch_num;
-	int h_ch_num;
-	int ch_count;
-	enum sdw_data_direction dir;
-	enum sdw_stream_type type;
-};
-
 /**
  * struct sdw_cdns_streams: Cadence stream data structure
  *
@@ -140,6 +121,7 @@ struct sdw_cdns {
 	int num_ports;
 
 	struct sdw_cdns_streams pcm;
+	spinlock_t pdi_lock;
 
 	int pdi_loopback_source;
 	int pdi_loopback_target;
diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index af65214836b4..d53fa3d299bc 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -674,6 +674,22 @@ intel_pdi_alh_configure(struct sdw_intel *sdw, struct sdw_cdns_pdi *pdi)
 	intel_writel(alh, SDW_ALH_STRMZCFG(pdi->intel_alh_id), conf);
 }
 
+/**
+ * sdw_intel_pdi_config - Configure specified PDI
+ * @bus: SoundWire bus instance
+ * @pdi: PDI instance to configure
+ */
+void sdw_intel_pdi_config(struct sdw_bus *bus, struct sdw_cdns_pdi *pdi)
+{
+	struct sdw_cdns *cdns = bus_to_cdns(bus);
+	struct sdw_intel *sdw = cdns_to_intel(cdns);
+
+	intel_pdi_shim_configure(sdw, pdi);
+	intel_pdi_alh_configure(sdw, pdi);
+	sdw_cdns_config_stream(cdns, pdi->ch_count, pdi->dir, pdi);
+}
+EXPORT_SYMBOL(sdw_intel_pdi_config);
+
 static int intel_params_stream(struct sdw_intel *sdw,
 			       struct snd_pcm_substream *substream,
 			       struct snd_soc_dai *dai,
diff --git a/include/linux/soundwire/sdw_cadence.h b/include/linux/soundwire/sdw_cadence.h
new file mode 100644
index 000000000000..331b21adafc4
--- /dev/null
+++ b/include/linux/soundwire/sdw_cadence.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/* Copyright(c) 2024-2026 Intel Corporation */
+
+#ifndef ___SDW_CADENCE_H
+#define ___SDW_CADENCE_H
+
+#include <linux/soundwire/sdw.h>
+
+/**
+ * struct sdw_cdns_pdi: PDI (Physical Data Interface) instance
+ *
+ * @num: pdi number
+ * @intel_alh_id: link identifier
+ * @l_ch_num: low channel for PDI
+ * @h_ch_num: high channel for PDI
+ * @ch_count: total channel count for PDI
+ * @dir: data direction
+ * @type: stream type, (only PCM supported)
+ * @assigned: whether PDI is in use
+ */
+struct sdw_cdns_pdi {
+	int num;
+	int intel_alh_id;
+	int l_ch_num;
+	int h_ch_num;
+	int ch_count;
+	enum sdw_data_direction dir;
+	enum sdw_stream_type type;
+	bool assigned;
+};
+
+struct sdw_cdns_pdi *sdw_cdns_assign_pdi(struct sdw_bus *bus, u32 dir);
+void sdw_cdns_release_pdi(struct sdw_bus *bus, struct sdw_cdns_pdi *pdi);
+
+#endif
diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h
index 83021cc0f5b8..120f16b8d478 100644
--- a/include/linux/soundwire/sdw_intel.h
+++ b/include/linux/soundwire/sdw_intel.h
@@ -7,6 +7,7 @@
 #include <linux/acpi.h>
 #include <linux/irqreturn.h>
 #include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_cadence.h>
 
 /*********************************************************************
  * cAVS and ACE1.x definitions
@@ -386,6 +387,8 @@ void sdw_intel_exit(struct sdw_intel_ctx *ctx);
 
 irqreturn_t sdw_intel_thread(int irq, void *dev_id);
 
+void sdw_intel_pdi_config(struct sdw_bus *bus, struct sdw_cdns_pdi *pdi);
+
 #else
 
 static inline int sdw_intel_acpi_scan(acpi_handle parent_handle, struct sdw_intel_acpi_info *info)
@@ -416,6 +419,10 @@ static inline irqreturn_t sdw_intel_thread(int irq, void *dev_id)
 	return 0;
 }
 
+static inline void sdw_intel_pdi_config(struct sdw_bus *bus, struct sdw_cdns_pdi *pdi)
+{
+}
+
 #endif
 
 #define SDW_INTEL_QUIRK_MASK_BUS_DISABLE      BIT(1)
-- 
2.34.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 3/7] soundwire: intel: Split PDIs and DAIs initialization
  2026-11-02 18:10 [PATCH 0/7] ASoC: Intel: avs: Soundwire support Cezary Rojewski
  2026-11-02 18:10 ` [PATCH 1/7] soundwire: intel: Define stubs when library is disabled Cezary Rojewski
  2026-11-02 18:10 ` [PATCH 2/7] soundwire: intel: Allow for dynamic assignment of PDIs Cezary Rojewski
@ 2026-11-02 18:10 ` Cezary Rojewski
  2026-11-02 18:10 ` [PATCH 4/7] ASoC: Intel: avs: Pass irq to dsp_interrupt callback Cezary Rojewski
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Cezary Rojewski @ 2026-11-02 18:10 UTC (permalink / raw)
  To: linux-sound
  Cc: broonie, tiwai, perex, amade, linux-kernel, yung-chuan.liao,
	pierre-louis.bossart, vkoul, Cezary Rojewski

Not every client of the soundwire-driver needs the secondary
soc-component and full range of DAIs immediately when initializing the
device. As function intel_register_dai() does all of that on top of
initializing PDIs, split it into two logical blocks to accommodate for
both approaches. In consequence, register_dai() callback becomes
optional.

To keep things in status quo for existing users, update
intel_link_startup() to call sdw_intel_init_pdis().

Cc: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
 drivers/soundwire/intel.c           | 24 +++++++++++++++---------
 drivers/soundwire/intel.h           |  3 ++-
 drivers/soundwire/intel_auxdevice.c |  4 ++++
 3 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index d53fa3d299bc..708503373183 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -1027,23 +1027,29 @@ static int intel_create_dai(struct sdw_cdns *cdns,
 	return 0;
 }
 
+int sdw_intel_init_pdis(struct sdw_intel *sdw)
+{
+	struct sdw_cdns_stream_config config;
+	int ret;
+
+	/* Read the PDI config and initialize cadence PDI */
+	intel_pdi_init(sdw, &config);
+	ret = sdw_cdns_pdi_init(&sdw->cdns, config);
+	if (ret)
+		return ret;
+
+	intel_pdi_stream_ch_update(sdw, &sdw->cdns.pcm);
+	return 0;
+}
+
 static int intel_register_dai(struct sdw_intel *sdw)
 {
 	struct sdw_cdns_dai_runtime **dai_runtime_array;
-	struct sdw_cdns_stream_config config;
 	struct sdw_cdns *cdns = &sdw->cdns;
 	struct sdw_cdns_streams *stream;
 	struct snd_soc_dai_driver *dais;
 	int num_dai, ret, off = 0;
 
-	/* Read the PDI config and initialize cadence PDI */
-	intel_pdi_init(sdw, &config);
-	ret = sdw_cdns_pdi_init(cdns, config);
-	if (ret)
-		return ret;
-
-	intel_pdi_stream_ch_update(sdw, &sdw->cdns.pcm);
-
 	/* DAIs are created based on total number of PDIs supported */
 	num_dai = cdns->pcm.num_pdi;
 
diff --git a/drivers/soundwire/intel.h b/drivers/soundwire/intel.h
index 7a2e7e73ad63..12416cef8224 100644
--- a/drivers/soundwire/intel.h
+++ b/drivers/soundwire/intel.h
@@ -158,7 +158,7 @@ static inline int sdw_intel_register_dai(struct sdw_intel *sdw)
 {
 	if (SDW_INTEL_CHECK_OPS(sdw, register_dai))
 		return SDW_INTEL_OPS(sdw, register_dai)(sdw);
-	return -ENOTSUPP;
+	return 0;
 }
 
 static inline void sdw_intel_check_clock_stop(struct sdw_intel *sdw)
@@ -262,6 +262,7 @@ int intel_start_bus_after_reset(struct sdw_intel *sdw);
 void intel_check_clock_stop(struct sdw_intel *sdw);
 int intel_start_bus_after_clock_stop(struct sdw_intel *sdw);
 int intel_stop_bus(struct sdw_intel *sdw, bool clock_stop, bool wake_enable);
+int sdw_intel_init_pdis(struct sdw_intel *sdw);
 
 /* common bank switch routines */
 int intel_pre_bank_switch(struct sdw_intel *sdw);
diff --git a/drivers/soundwire/intel_auxdevice.c b/drivers/soundwire/intel_auxdevice.c
index 5983fbc5725a..114dadedfa14 100644
--- a/drivers/soundwire/intel_auxdevice.c
+++ b/drivers/soundwire/intel_auxdevice.c
@@ -423,6 +423,10 @@ int intel_link_startup(struct auxiliary_device *auxdev)
 	if (ret)
 		goto err_init;
 
+	ret = sdw_intel_init_pdis(sdw);
+	if (ret)
+		goto err_init;
+
 	/* Register DAIs */
 	ret = sdw_intel_register_dai(sdw);
 	if (ret) {
-- 
2.34.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 4/7] ASoC: Intel: avs: Pass irq to dsp_interrupt callback
  2026-11-02 18:10 [PATCH 0/7] ASoC: Intel: avs: Soundwire support Cezary Rojewski
                   ` (2 preceding siblings ...)
  2026-11-02 18:10 ` [PATCH 3/7] soundwire: intel: Split PDIs and DAIs initialization Cezary Rojewski
@ 2026-11-02 18:10 ` Cezary Rojewski
  2026-11-02 18:10 ` [PATCH 5/7] ASoC: Intel: avs: SoundWire support Cezary Rojewski
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Cezary Rojewski @ 2026-11-02 18:10 UTC (permalink / raw)
  To: linux-sound
  Cc: broonie, tiwai, perex, amade, linux-kernel, yung-chuan.liao,
	pierre-louis.bossart, vkoul, Cezary Rojewski

Soundwire IRQ thread function requires passing irq as one of the
arguments, as we will want to call it in dsp_interrupt callback, it
needs to be passed throguh.

Signed-off-by: Amadeusz Sławiński <amade@asmblr.net>
Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
 sound/soc/intel/avs/apl.c  | 2 +-
 sound/soc/intel/avs/avs.h  | 6 +++---
 sound/soc/intel/avs/cnl.c  | 2 +-
 sound/soc/intel/avs/core.c | 2 +-
 sound/soc/intel/avs/mtl.c  | 2 +-
 sound/soc/intel/avs/skl.c  | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/sound/soc/intel/avs/apl.c b/sound/soc/intel/avs/apl.c
index cf600e1c986e..3abcdf062035 100644
--- a/sound/soc/intel/avs/apl.c
+++ b/sound/soc/intel/avs/apl.c
@@ -17,7 +17,7 @@
 #include "registers.h"
 #include "topology.h"
 
-static irqreturn_t avs_apl_dsp_interrupt(struct avs_dev *adev)
+static irqreturn_t avs_apl_dsp_interrupt(struct avs_dev *adev, int irq)
 {
 	u32 adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS);
 	irqreturn_t ret = IRQ_NONE;
diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h
index b4f9d66d55ad..b3af2c4126be 100644
--- a/sound/soc/intel/avs/avs.h
+++ b/sound/soc/intel/avs/avs.h
@@ -45,7 +45,7 @@ struct avs_dsp_ops {
 	int (* const power)(struct avs_dev *, u32, bool);
 	int (* const reset)(struct avs_dev *, u32, bool);
 	int (* const stall)(struct avs_dev *, u32, bool);
-	irqreturn_t (* const dsp_interrupt)(struct avs_dev *);
+	irqreturn_t (* const dsp_interrupt)(struct avs_dev *, int irq);
 	void (* const int_control)(struct avs_dev *, bool);
 	int (* const load_basefw)(struct avs_dev *, struct firmware *);
 	int (* const load_lib)(struct avs_dev *, struct firmware *, u32);
@@ -273,8 +273,8 @@ int avs_mtl_core_stall(struct avs_dev *adev, u32 core_mask, bool stall);
 int avs_lnl_core_stall(struct avs_dev *adev, u32 core_mask, bool stall);
 void avs_mtl_interrupt_control(struct avs_dev *adev, bool enable);
 void avs_skl_ipc_interrupt(struct avs_dev *adev);
-irqreturn_t avs_cnl_dsp_interrupt(struct avs_dev *adev);
-irqreturn_t avs_mtl_dsp_interrupt(struct avs_dev *adev);
+irqreturn_t avs_cnl_dsp_interrupt(struct avs_dev *adev, int irq);
+irqreturn_t avs_mtl_dsp_interrupt(struct avs_dev *adev, int irq);
 int avs_apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
 			u32 fifo_full_period, unsigned long resource_mask, u32 *priorities);
 int avs_icl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period,
diff --git a/sound/soc/intel/avs/cnl.c b/sound/soc/intel/avs/cnl.c
index 5b5359e9128b..31fd9f251d6c 100644
--- a/sound/soc/intel/avs/cnl.c
+++ b/sound/soc/intel/avs/cnl.c
@@ -58,7 +58,7 @@ static void avs_cnl_ipc_interrupt(struct avs_dev *adev)
 			      AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY);
 }
 
-irqreturn_t avs_cnl_dsp_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);
 	irqreturn_t ret = IRQ_NONE;
diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c
index 611ae9f034d4..9413027e1e32 100644
--- a/sound/soc/intel/avs/core.c
+++ b/sound/soc/intel/avs/core.c
@@ -344,7 +344,7 @@ static irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id)
 
 	status = readl(bus->ppcap + AZX_REG_PP_PPSTS);
 	if (status & AZX_PPCTL_PIE)
-		avs_dsp_op(adev, dsp_interrupt);
+		avs_dsp_op(adev, dsp_interrupt, irq);
 
 	/* Unmask GIE, masked in irq_handler(). */
 	snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_GLOBAL_EN, AZX_INT_GLOBAL_EN);
diff --git a/sound/soc/intel/avs/mtl.c b/sound/soc/intel/avs/mtl.c
index d8bdd03275d7..29f79d6ff0d4 100644
--- a/sound/soc/intel/avs/mtl.c
+++ b/sound/soc/intel/avs/mtl.c
@@ -166,7 +166,7 @@ static void avs_mtl_ipc_interrupt(struct avs_dev *adev)
 			      AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY);
 }
 
-irqreturn_t avs_mtl_dsp_interrupt(struct avs_dev *adev)
+irqreturn_t avs_mtl_dsp_interrupt(struct avs_dev *adev, int irq)
 {
 	u32 adspis = snd_hdac_adsp_readl(adev, MTL_DWICTL_REG_FINALSTATUSL);
 	irqreturn_t ret = IRQ_NONE;
diff --git a/sound/soc/intel/avs/skl.c b/sound/soc/intel/avs/skl.c
index 8fb86f364ff3..54c883658cca 100644
--- a/sound/soc/intel/avs/skl.c
+++ b/sound/soc/intel/avs/skl.c
@@ -54,7 +54,7 @@ void avs_skl_ipc_interrupt(struct avs_dev *adev)
 			      AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY);
 }
 
-static irqreturn_t avs_skl_dsp_interrupt(struct avs_dev *adev)
+static irqreturn_t avs_skl_dsp_interrupt(struct avs_dev *adev, int irq)
 {
 	u32 adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS);
 	irqreturn_t ret = IRQ_NONE;
-- 
2.34.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 5/7] ASoC: Intel: avs: SoundWire support
  2026-11-02 18:10 [PATCH 0/7] ASoC: Intel: avs: Soundwire support Cezary Rojewski
                   ` (3 preceding siblings ...)
  2026-11-02 18:10 ` [PATCH 4/7] ASoC: Intel: avs: Pass irq to dsp_interrupt callback Cezary Rojewski
@ 2026-11-02 18:10 ` Cezary Rojewski
  2026-11-02 18:10 ` [PATCH 6/7] ASoC: Intel: avs: Expose common PCM functions Cezary Rojewski
  2026-11-02 18:10 ` [PATCH 7/7] ASoC: Intel: avs: SoundWire PCM BE operations Cezary Rojewski
  6 siblings, 0 replies; 10+ messages in thread
From: Cezary Rojewski @ 2026-11-02 18:10 UTC (permalink / raw)
  To: linux-sound
  Cc: broonie, tiwai, perex, amade, linux-kernel, yung-chuan.liao,
	pierre-louis.bossart, vkoul, Cezary Rojewski

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         |   1 +
 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      |  22 +++++++
 sound/soc/intel/avs/loader.c    |   3 +
 sound/soc/intel/avs/registers.h |   4 ++
 sound/soc/intel/avs/soundwire.c | 112 ++++++++++++++++++++++++++++++++
 sound/soc/intel/avs/soundwire.h |  56 ++++++++++++++++
 9 files changed, 224 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..4e453b55fc04 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -106,6 +106,7 @@ 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
diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile
index 576dc0da381d..1d48953c7a31 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_SOUNDWIRE_INTEL),)
+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..f9f25f651a9e 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);
@@ -587,6 +603,9 @@ static void avs_pci_remove(struct pci_dev *pci)
 	avs_dsp_op(adev, int_control, false);
 	snd_hdac_ext_bus_ppcap_int_enable(bus, false);
 
+	avs_sdw_enable_irq(adev, false);
+	avs_sdw_exit(adev);
+
 	/* it is safe to remove all codecs from the system now */
 	list_for_each_entry_safe(hdev, save, &bus->codec_list, list)
 		snd_hda_codec_unregister(hdac_to_hda_codec(hdev));
@@ -661,6 +680,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 +740,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..c2a6db08a3af
--- /dev/null
+++ b/sound/soc/intel/avs/soundwire.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright(c) 2021-2026 Intel Corporation
+//
+// Authors: Cezary Rojewski <cezary.rojewski@intel.com>
+//          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
+//
+
+#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;
+
+	ret = sdw_intel_acpi_scan(ACPI_HANDLE(adev->dev), &info);
+	if (ret < 0)
+		return -ENODEV;
+
+	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)
+{
+	if (adev->sdw) {
+		sdw_intel_exit(adev->sdw);
+		adev->sdw = NULL;
+	}
+}
+
+// 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..96ce29ab21a3
--- /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 <amadeuszx.slawinski@linux.intel.com>
+ */
+
+#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_SOUNDWIRE_INTEL)
+
+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


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 6/7] ASoC: Intel: avs: Expose common PCM functions
  2026-11-02 18:10 [PATCH 0/7] ASoC: Intel: avs: Soundwire support Cezary Rojewski
                   ` (4 preceding siblings ...)
  2026-11-02 18:10 ` [PATCH 5/7] ASoC: Intel: avs: SoundWire support Cezary Rojewski
@ 2026-11-02 18:10 ` Cezary Rojewski
  2026-11-02 18:18   ` Amadeusz Sławiński
  2026-11-02 18:10 ` [PATCH 7/7] ASoC: Intel: avs: SoundWire PCM BE operations Cezary Rojewski
  6 siblings, 1 reply; 10+ messages in thread
From: Cezary Rojewski @ 2026-11-02 18:10 UTC (permalink / raw)
  To: linux-sound
  Cc: broonie, tiwai, perex, amade, linux-kernel, yung-chuan.liao,
	pierre-louis.bossart, vkoul, Cezary Rojewski

All the PCM operations are currently bundled together within the pcm.c
file regardless of which transfer type they cover. To allow for
splitting them, provide a header that exposes the common operations
outside.

Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
 sound/soc/intel/avs/avs.h |  8 -------
 sound/soc/intel/avs/pcm.c | 42 +++++++++------------------------
 sound/soc/intel/avs/pcm.h | 49 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 39 deletions(-)

diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h
index 40e65639adb2..1b2f1e7d0556 100644
--- a/sound/soc/intel/avs/avs.h
+++ b/sound/soc/intel/avs/avs.h
@@ -347,14 +347,6 @@ struct avs_soc_component {
 
 extern const struct snd_soc_dai_ops avs_dai_fe_ops;
 
-int avs_register_dmic_component(struct avs_dev *adev, const char *name);
-int avs_register_i2s_component(struct avs_dev *adev, const char *name, unsigned long port_mask,
-			       unsigned long *tdms);
-int avs_register_hda_component(struct avs_dev *adev, const char *name);
-int avs_register_component(struct device *dev, const char *name,
-			   struct snd_soc_component_driver *drv,
-			   struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais);
-
 int avs_register_all_boards(struct avs_dev *adev);
 void avs_unregister_all_boards(struct avs_dev *adev);
 
diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c
index f17bbc2ba63d..fb1af3bb493f 100644
--- a/sound/soc/intel/avs/pcm.c
+++ b/sound/soc/intel/avs/pcm.c
@@ -22,26 +22,6 @@
 #include "utils.h"
 #include "../../codecs/hda.h"
 
-struct avs_dma_data {
-	struct avs_tplg_path_template *template;
-	struct avs_path *path;
-	struct avs_dev *adev;
-
-	/* LINK-stream utilized in BE operations while HOST in FE ones. */
-	union {
-		struct hdac_ext_stream *link_stream;
-		struct hdac_ext_stream *host_stream;
-	};
-
-	struct snd_pcm_hw_constraint_list rate_list;
-	struct snd_pcm_hw_constraint_list channels_list;
-	struct snd_pcm_hw_constraint_list sample_bits_list;
-
-	struct work_struct period_elapsed_work;
-	struct hdac_ext_link *link;
-	struct snd_pcm_substream *substream;
-};
-
 static struct avs_tplg_path_template *
 avs_dai_find_path_template(struct snd_soc_dai *dai, bool is_fe, int direction)
 {
@@ -117,7 +97,7 @@ static int avs_hw_constraints_init(struct snd_pcm_substream *substream, struct s
 	return 0;
 }
 
-static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
 {
 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 	struct avs_dev *adev = to_avs_dev(dai->component->dev);
@@ -147,7 +127,7 @@ static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_d
 	return avs_hw_constraints_init(substream, dai);
 }
 
-static void avs_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+void avs_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
 {
 	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
 	struct avs_dma_data *data;
@@ -165,10 +145,10 @@ static void avs_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc
 	kfree(data);
 }
 
-static int avs_dai_hw_params(struct snd_pcm_substream *substream,
-			     struct snd_pcm_hw_params *fe_hw_params,
-			     struct snd_pcm_hw_params *be_hw_params, struct snd_soc_dai *dai,
-			     int dma_id)
+int avs_dai_hw_params(struct snd_pcm_substream *substream,
+		      struct snd_pcm_hw_params *fe_hw_params,
+		      struct snd_pcm_hw_params *be_hw_params,
+		      struct snd_soc_dai *dai, int dma_id)
 {
 	struct avs_dma_data *data;
 	struct avs_path *path;
@@ -199,9 +179,9 @@ static int avs_dai_hw_params(struct snd_pcm_substream *substream,
 	return 0;
 }
 
-static int avs_dai_be_hw_params(struct snd_pcm_substream *substream,
-				struct snd_pcm_hw_params *be_hw_params, struct snd_soc_dai *dai,
-				int dma_id)
+int avs_dai_be_hw_params(struct snd_pcm_substream *substream,
+			 struct snd_pcm_hw_params *be_hw_params,
+			 struct snd_soc_dai *dai, int dma_id)
 {
 	struct snd_pcm_hw_params *fe_hw_params = NULL;
 	struct snd_soc_pcm_runtime *fe, *be;
@@ -217,7 +197,7 @@ static int avs_dai_be_hw_params(struct snd_pcm_substream *substream,
 	return avs_dai_hw_params(substream, fe_hw_params, be_hw_params, dai, dma_id);
 }
 
-static int avs_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+int avs_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
 {
 	struct avs_dma_data *data;
 	int ret;
@@ -1376,7 +1356,7 @@ static int avs_component_new(struct snd_soc_component *component,
 	return 0;
 }
 
-static struct snd_soc_component_driver avs_component_driver = {
+struct snd_soc_component_driver avs_component_driver = {
 	.name			= "avs-pcm",
 	.probe			= avs_component_probe,
 	.remove			= avs_component_remove,
diff --git a/sound/soc/intel/avs/pcm.h b/sound/soc/intel/avs/pcm.h
index 0f3615c90398..ac127ade4ca1 100644
--- a/sound/soc/intel/avs/pcm.h
+++ b/sound/soc/intel/avs/pcm.h
@@ -9,8 +9,57 @@
 #ifndef __SOUND_SOC_INTEL_AVS_PCM_H
 #define __SOUND_SOC_INTEL_AVS_PCM_H
 
+#include <linux/device.h>
+#include <sound/hdaudio_ext.h>
 #include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-acpi.h>
+#include <sound/pcm_params.h>
+#include <sound/soc-acpi.h>
+#include <sound/soc-acpi-intel-match.h>
+#include <sound/soc-component.h>
+#include <sound/soc-dai.h>
+
+struct avs_dma_data {
+	struct avs_tplg_path_template *template;
+	struct avs_path *path;
+	struct avs_dev *adev;
+
+	/* LINK-stream utilized in BE operations while HOST in FE ones. */
+	union {
+		struct hdac_ext_stream *link_stream;
+		struct hdac_ext_stream *host_stream;
+	};
+
+	struct snd_pcm_hw_constraint_list rate_list;
+	struct snd_pcm_hw_constraint_list channels_list;
+	struct snd_pcm_hw_constraint_list sample_bits_list;
+
+	struct work_struct period_elapsed_work;
+	struct hdac_ext_link *link;
+	struct snd_pcm_substream *substream;
+};
 
 void avs_period_elapsed(struct snd_pcm_substream *substream);
+int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai);
+void avs_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai);
+int avs_dai_hw_params(struct snd_pcm_substream *substream,
+		      struct snd_pcm_hw_params *fe_params,
+		      struct snd_pcm_hw_params *be_params,
+		      struct snd_soc_dai *dai, int dma_id);
+int avs_dai_be_hw_params(struct snd_pcm_substream *substream,
+			 struct snd_pcm_hw_params *be_params,
+			 struct snd_soc_dai *dai, int dma_id);
+int avs_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai);
+
+extern struct snd_soc_component_driver avs_component_driver;
+int avs_register_component(struct device *dev, const char *name,
+			   struct snd_soc_component_driver *drv,
+			   struct snd_soc_dai_driver *cpu_dais, int num_cpu_dais);
+
+int avs_register_dmic_component(struct avs_dev *adev, const char *name);
+int avs_register_i2s_component(struct avs_dev *adev, const char *name, unsigned long port_mask,
+			       unsigned long *tdms);
+int avs_register_hda_component(struct avs_dev *adev, const char *name);
 
 #endif
-- 
2.34.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 7/7] ASoC: Intel: avs: SoundWire PCM BE operations
  2026-11-02 18:10 [PATCH 0/7] ASoC: Intel: avs: Soundwire support Cezary Rojewski
                   ` (5 preceding siblings ...)
  2026-11-02 18:10 ` [PATCH 6/7] ASoC: Intel: avs: Expose common PCM functions Cezary Rojewski
@ 2026-11-02 18:10 ` Cezary Rojewski
  6 siblings, 0 replies; 10+ messages in thread
From: Cezary Rojewski @ 2026-11-02 18:10 UTC (permalink / raw)
  To: linux-sound
  Cc: broonie, tiwai, perex, amade, linux-kernel, yung-chuan.liao,
	pierre-louis.bossart, vkoul, Cezary Rojewski

Implement the back-end PCM operations for the SoundWire Link to support
data transfer over SoundWire interface. Most of the actual job is done
by the SoundWire library, thus code added here just invokes them in
correct order.

Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
 sound/soc/intel/avs/Makefile    |   2 +-
 sound/soc/intel/avs/messages.h  |   2 +
 sound/soc/intel/avs/path.c      |   2 +
 sound/soc/intel/avs/pcm.h       |   2 +
 sound/soc/intel/avs/pcm_sdw.c   | 276 ++++++++++++++++++++++++++++++++
 sound/soc/intel/avs/soundwire.h |   7 +
 6 files changed, 290 insertions(+), 1 deletion(-)
 create mode 100644 sound/soc/intel/avs/pcm_sdw.c

diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile
index 1d48953c7a31..07a82a6f5b23 100644
--- a/sound/soc/intel/avs/Makefile
+++ b/sound/soc/intel/avs/Makefile
@@ -15,7 +15,7 @@ snd-soc-avs-y += probes.o debugfs.o
 endif
 
 ifneq ($(CONFIG_SOUNDWIRE_INTEL),)
-snd-soc-avs-y += soundwire.o
+snd-soc-avs-y += soundwire.o pcm_sdw.o
 endif
 
 obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o
diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h
index 55c04b0142ae..d1ffc640dda2 100644
--- a/sound/soc/intel/avs/messages.h
+++ b/sound/soc/intel/avs/messages.h
@@ -750,6 +750,8 @@ enum avs_dma_type {
 	AVS_DMA_DMIC_LINK_INPUT = 11,
 	AVS_DMA_I2S_LINK_OUTPUT = 12,
 	AVS_DMA_I2S_LINK_INPUT = 13,
+	AVS_DMA_SDW_LINK_OUTPUT = 16,
+	AVS_DMA_SDW_LINK_INPUT = 17,
 };
 
 union avs_virtual_index {
diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c
index a8a2b3484338..60d9245894e7 100644
--- a/sound/soc/intel/avs/path.c
+++ b/sound/soc/intel/avs/path.c
@@ -260,6 +260,8 @@ static void avs_init_node_id(union avs_connector_node_id *node_id,
 
 	case AVS_DMA_HDA_LINK_OUTPUT:
 	case AVS_DMA_HDA_LINK_INPUT:
+	case AVS_DMA_SDW_LINK_OUTPUT:
+	case AVS_DMA_SDW_LINK_INPUT:
 		node_id->vindex = te->copier.vindex.val | dma_id;
 		break;
 
diff --git a/sound/soc/intel/avs/pcm.h b/sound/soc/intel/avs/pcm.h
index ac127ade4ca1..66d6896a4af7 100644
--- a/sound/soc/intel/avs/pcm.h
+++ b/sound/soc/intel/avs/pcm.h
@@ -37,6 +37,8 @@ struct avs_dma_data {
 
 	struct work_struct period_elapsed_work;
 	struct hdac_ext_link *link;
+	struct sdw_stream_runtime *sdw_stream;
+	struct sdw_cdns_pdi *pdi;
 	struct snd_pcm_substream *substream;
 };
 
diff --git a/sound/soc/intel/avs/pcm_sdw.c b/sound/soc/intel/avs/pcm_sdw.c
new file mode 100644
index 000000000000..27cb285eca09
--- /dev/null
+++ b/sound/soc/intel/avs/pcm_sdw.c
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// Copyright(c) 2024-2026 Intel Corporation
+//
+// Authors: Cezary Rojewski <cezary.rojewski@intel.com>
+//          Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
+//
+
+#include <linux/device.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_intel.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include <sound/soc-component.h>
+#include <sound/soc-dai.h>
+#include "avs.h"
+#include "path.h"
+#include "pcm.h"
+#include "soundwire.h"
+#include "topology.h"
+
+static int avs_sdw_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+	struct sdw_stream_runtime *sdw_stream;
+	struct snd_soc_acpi_mach *mach;
+	struct snd_soc_dai *codec_dai;
+	struct avs_dma_data *data;
+	struct sdw_cdns_pdi *pdi;
+	struct sdw_slave *codec;
+	int dir, ret;
+
+	mach = dev_get_platdata(dai->component->card->dev);
+	codec = mach->pdata;
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		dir = SDW_DATA_DIR_RX;
+	else
+		dir = SDW_DATA_DIR_TX;
+
+	ret = avs_dai_startup(substream, dai);
+	if (ret)
+		return ret;
+
+	sdw_stream = sdw_alloc_stream(substream->name, SDW_STREAM_PCM);
+	if (!sdw_stream) {
+		ret = -ENOMEM;
+		goto err_alloc_stream;
+	}
+
+	pdi = sdw_cdns_assign_pdi(codec->bus, dir);
+	if (!pdi) {
+		ret = -EBUSY;
+		goto err_assign_pdi;
+	}
+
+	/* Fulfill the codec needs by setting the sdw_stream. */
+	codec_dai = snd_soc_rtd_to_codec(rtd, 0);
+	snd_soc_dai_set_stream(codec_dai, sdw_stream, substream->stream);
+
+	data = snd_soc_dai_get_dma_data(dai, substream);
+	data->sdw_stream = sdw_stream;
+	data->pdi = pdi;
+	return 0;
+
+err_assign_pdi:
+	sdw_release_stream(sdw_stream);
+err_alloc_stream:
+	avs_dai_shutdown(substream, dai);
+	return ret;
+}
+
+static void avs_sdw_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+{
+	struct snd_soc_acpi_mach *mach;
+	struct avs_dma_data *data;
+	struct sdw_slave *codec;
+
+	data = snd_soc_dai_get_dma_data(dai, substream);
+	mach = dev_get_platdata(dai->component->card->dev);
+	codec = mach->pdata;
+
+	sdw_cdns_release_pdi(codec->bus, data->pdi);
+	sdw_release_stream(data->sdw_stream);
+	avs_dai_shutdown(substream, dai);
+}
+
+static int avs_sdw_dai_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *hw_params,
+				 struct snd_soc_dai *dai)
+{
+	struct sdw_stream_config sconfig = {0};
+	struct sdw_port_config pconfig = {0};
+	struct snd_soc_acpi_mach *mach;
+	struct avs_dma_data *data;
+	struct sdw_cdns_pdi *pdi;
+	struct sdw_slave *codec;
+	int ret;
+
+	data = snd_soc_dai_get_dma_data(dai, substream);
+	if (data->path)
+		return 0;
+
+	mach = dev_get_platdata(dai->component->card->dev);
+	codec = mach->pdata;
+	pdi = data->pdi;
+	pdi->ch_count = params_channels(hw_params);
+	pdi->h_ch_num = pdi->ch_count - 1;
+	pdi->l_ch_num = 0;
+	sdw_intel_pdi_config(codec->bus, pdi);
+
+	sconfig.direction = pdi->dir;
+	sconfig.ch_count = pdi->ch_count;
+	sconfig.frame_rate = params_rate(hw_params);
+	sconfig.type = SDW_STREAM_PCM;
+	sconfig.bps = snd_pcm_format_width(params_format(hw_params));
+	pconfig.num = pdi->num;
+	pconfig.ch_mask = (1 << pdi->ch_count) - 1;
+
+	ret = sdw_stream_add_master(codec->bus, &sconfig, &pconfig, 1, data->sdw_stream);
+	if (ret)
+		return ret;
+
+	ret = avs_dai_be_hw_params(substream, hw_params, dai, pdi->intel_alh_id);
+	if (ret)
+		sdw_stream_remove_master(codec->bus, data->sdw_stream);
+	return ret;
+}
+
+static int avs_sdw_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+{
+	struct snd_soc_acpi_mach *mach;
+	struct avs_dma_data *data;
+	struct sdw_slave *codec;
+	int ret;
+
+	data = snd_soc_dai_get_dma_data(dai, substream);
+	if (!data->path)
+		return 0;
+
+	mach = dev_get_platdata(dai->component->card->dev);
+	codec = mach->pdata;
+
+	ret = avs_path_reset(data->path);
+	if (ret < 0)
+		dev_err(dai->dev, "reset BE path failed: %d\n", ret);
+	avs_path_free(data->path);
+	data->path = NULL;
+	sdw_deprepare_stream(data->sdw_stream);
+	sdw_stream_remove_master(codec->bus, data->sdw_stream);
+
+	return 0;
+}
+
+static int avs_sdw_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+{
+	struct avs_dma_data *data;
+	int ret;
+
+	data = snd_soc_dai_get_dma_data(dai, substream);
+
+	ret = sdw_prepare_stream(data->sdw_stream);
+	if (ret) {
+		dev_err(dai->dev, "sdw stream prepare failed: %d\n", ret);
+		return ret;
+	}
+
+	return avs_dai_prepare(substream, dai);
+}
+
+static int avs_sdw_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+			       struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+	struct avs_dma_data *data;
+	int ret = 0;
+
+	data = snd_soc_dai_get_dma_data(dai, substream);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_RESUME:
+		if (rtd->dai_link->ignore_suspend)
+			break;
+		fallthrough;
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		ret = sdw_enable_stream(data->sdw_stream);
+		if (ret)
+			break;
+
+		ret = avs_path_run(data->path, AVS_TPLG_TRIGGER_AUTO);
+		if (ret < 0)
+			dev_err(dai->dev, "run BE path failed: %d\n", ret);
+		break;
+
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		if (rtd->dai_link->ignore_suspend)
+			break;
+		fallthrough;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_STOP:
+		ret = avs_path_pause(data->path);
+		if (ret < 0)
+			dev_err(dai->dev, "pause BE path failed: %d\n", ret);
+
+		ret = sdw_disable_stream(data->sdw_stream);
+		if (ret)
+			dev_err(dai->dev, "disable sdw stream failed: %d\n", ret);
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static const struct snd_soc_dai_ops avs_sdw_dai_ops = {
+	.startup = avs_sdw_dai_startup,
+	.shutdown = avs_sdw_dai_shutdown,
+	.hw_params = avs_sdw_dai_hw_params,
+	.hw_free = avs_sdw_dai_hw_free,
+	.prepare = avs_sdw_dai_prepare,
+	.trigger = avs_sdw_dai_trigger,
+};
+
+static const struct snd_soc_dai_driver avs_sdw_dai_template = {
+	.playback = {
+		.channels_min	= 1,
+		.channels_max	= 8,
+		.rates		= SNDRV_PCM_RATE_8000_192000 |
+				  SNDRV_PCM_RATE_KNOT,
+		.formats	= SNDRV_PCM_FMTBIT_S16_LE |
+				  SNDRV_PCM_FMTBIT_S32_LE,
+		.subformats	= SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
+				  SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
+				  SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
+	},
+	.capture = {
+		.channels_min	= 1,
+		.channels_max	= 8,
+		.rates		= SNDRV_PCM_RATE_8000_192000 |
+				  SNDRV_PCM_RATE_KNOT,
+		.formats	= SNDRV_PCM_FMTBIT_S16_LE |
+				  SNDRV_PCM_FMTBIT_S32_LE,
+		.subformats	= SNDRV_PCM_SUBFMTBIT_MSBITS_20 |
+				  SNDRV_PCM_SUBFMTBIT_MSBITS_24 |
+				  SNDRV_PCM_SUBFMTBIT_MSBITS_MAX,
+	},
+	.ops = &avs_sdw_dai_ops,
+};
+
+int avs_register_sdw_component(struct avs_dev *adev, const char *name, u32 link_id)
+{
+	struct snd_soc_dai_driver *dai;
+	struct device *dev = adev->dev;
+
+	dai = devm_kzalloc(dev, sizeof(*dai), GFP_KERNEL);
+	if (!dai)
+		return -ENOMEM;
+
+	memcpy(dai, &avs_sdw_dai_template, sizeof(*dai));
+
+	dai->name = devm_kasprintf(dev, GFP_KERNEL, "avs-sdw%d-pin", link_id);
+	if (!dai->name)
+		return -ENOMEM;
+
+	dai->playback.stream_name = devm_kasprintf(dev, GFP_KERNEL, "%s Tx", dai->name);
+	dai->capture.stream_name = devm_kasprintf(dev, GFP_KERNEL, "%s Rx", dai->name);
+
+	if (!dai->playback.stream_name || !dai->capture.stream_name)
+		return -ENOMEM;
+
+	return avs_register_component(dev, name, &avs_component_driver, dai, 1);
+}
diff --git a/sound/soc/intel/avs/soundwire.h b/sound/soc/intel/avs/soundwire.h
index 96ce29ab21a3..1cf77d5ec2d8 100644
--- a/sound/soc/intel/avs/soundwire.h
+++ b/sound/soc/intel/avs/soundwire.h
@@ -22,6 +22,8 @@ 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);
 
+int avs_register_sdw_component(struct avs_dev *adev, const char *name, u32 link_id);
+
 #else
 
 static inline int avs_sdw_probe(struct avs_dev *adev)
@@ -51,6 +53,11 @@ static inline irqreturn_t avs_sdw_thread(int irq, struct avs_dev *adev)
 	return IRQ_HANDLED;
 }
 
+static inline int avs_register_sdw_component(struct avs_dev *adev, const char *name, u32 link_id)
+{
+	return 0;
+}
+
 #endif
 
 #endif /* __SOUND_SOC_INTEL_AVS_SOUNDWIRE_H */
-- 
2.34.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 6/7] ASoC: Intel: avs: Expose common PCM functions
  2026-11-02 18:10 ` [PATCH 6/7] ASoC: Intel: avs: Expose common PCM functions Cezary Rojewski
@ 2026-11-02 18:18   ` Amadeusz Sławiński
  2026-11-02 18:20     ` Cezary Rojewski
  0 siblings, 1 reply; 10+ messages in thread
From: Amadeusz Sławiński @ 2026-11-02 18:18 UTC (permalink / raw)
  To: Cezary Rojewski
  Cc: linux-sound, broonie, tiwai, perex, linux-kernel,
	yung-chuan.liao, pierre-louis.bossart, vkoul

On Mon,  2 Nov 2026 19:10:41 +0100
Cezary Rojewski <cezary.rojewski@intel.com> wrote:

> diff --git a/sound/soc/intel/avs/pcm.h b/sound/soc/intel/avs/pcm.h
> index 0f3615c90398..ac127ade4ca1 100644
> --- a/sound/soc/intel/avs/pcm.h
> +++ b/sound/soc/intel/avs/pcm.h
> @@ -9,8 +9,57 @@
>  #ifndef __SOUND_SOC_INTEL_AVS_PCM_H
>  #define __SOUND_SOC_INTEL_AVS_PCM_H
>  
> +#include <linux/device.h>
> +#include <sound/hdaudio_ext.h>
>  #include <sound/pcm.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc-acpi.h>
> +#include <sound/pcm_params.h>
> +#include <sound/soc-acpi.h>
> +#include <sound/soc-acpi-intel-match.h>
> +#include <sound/soc-component.h>
> +#include <sound/soc-dai.h>

Some headers are included twice?



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 6/7] ASoC: Intel: avs: Expose common PCM functions
  2026-11-02 18:18   ` Amadeusz Sławiński
@ 2026-11-02 18:20     ` Cezary Rojewski
  0 siblings, 0 replies; 10+ messages in thread
From: Cezary Rojewski @ 2026-11-02 18:20 UTC (permalink / raw)
  To: Amadeusz Sławiński
  Cc: linux-sound, broonie, tiwai, perex, linux-kernel,
	yung-chuan.liao, pierre-louis.bossart, vkoul

On 11/2/2026 7:18 PM, Amadeusz Sławiński wrote:
> On Mon,  2 Nov 2026 19:10:41 +0100
> Cezary Rojewski <cezary.rojewski@intel.com> wrote:
> 
>> diff --git a/sound/soc/intel/avs/pcm.h b/sound/soc/intel/avs/pcm.h
>> index 0f3615c90398..ac127ade4ca1 100644
>> --- a/sound/soc/intel/avs/pcm.h
>> +++ b/sound/soc/intel/avs/pcm.h
>> @@ -9,8 +9,57 @@
>>  #ifndef __SOUND_SOC_INTEL_AVS_PCM_H
>>  #define __SOUND_SOC_INTEL_AVS_PCM_H
>>  
>> +#include <linux/device.h>
>> +#include <sound/hdaudio_ext.h>
>>  #include <sound/pcm.h>
>> +#include <sound/pcm_params.h>
>> +#include <sound/soc-acpi.h>
>> +#include <sound/pcm_params.h>
>> +#include <sound/soc-acpi.h>
>> +#include <sound/soc-acpi-intel-match.h>
>> +#include <sound/soc-component.h>
>> +#include <sound/soc-dai.h>
> 
> Some headers are included twice?

Indeed, ACK.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-11-02 18:20 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-02 18:10 [PATCH 0/7] ASoC: Intel: avs: Soundwire support Cezary Rojewski
2026-11-02 18:10 ` [PATCH 1/7] soundwire: intel: Define stubs when library is disabled Cezary Rojewski
2026-11-02 18:10 ` [PATCH 2/7] soundwire: intel: Allow for dynamic assignment of PDIs Cezary Rojewski
2026-11-02 18:10 ` [PATCH 3/7] soundwire: intel: Split PDIs and DAIs initialization Cezary Rojewski
2026-11-02 18:10 ` [PATCH 4/7] ASoC: Intel: avs: Pass irq to dsp_interrupt callback Cezary Rojewski
2026-11-02 18:10 ` [PATCH 5/7] ASoC: Intel: avs: SoundWire support Cezary Rojewski
2026-11-02 18:10 ` [PATCH 6/7] ASoC: Intel: avs: Expose common PCM functions Cezary Rojewski
2026-11-02 18:18   ` Amadeusz Sławiński
2026-11-02 18:20     ` Cezary Rojewski
2026-11-02 18:10 ` [PATCH 7/7] ASoC: Intel: avs: SoundWire PCM BE operations Cezary Rojewski

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®