Linux Sound subsystem development
 help / color / mirror / Atom feed
* [PATCH 00/11] ASoC/soundwire: add initial support for SDCA
@ 2024-10-16 10:23 Bard Liao
  2024-10-16 10:23 ` [PATCH 01/11] soundwire: sdw_intel: include linux/acpi.h Bard Liao
                   ` (11 more replies)
  0 siblings, 12 replies; 15+ messages in thread
From: Bard Liao @ 2024-10-16 10:23 UTC (permalink / raw)
  To: broonie, tiwai, vkoul
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

We need to get rt712 version by reading SDCA version and functions.
This patch series adds initial support for SDCA and add a helper to tell
if the codec is RT712_VB.

This series may go via the ASoC tree with Vinod's Acked-by tag.

Bard Liao (1):
  soundwire: sdw_intel: include linux/acpi.h

Pierre-Louis Bossart (10):
  ASoC/soundwire: remove sdw_slave_extended_id
  ASoC: SDCA: add initial module
  soundwire: slave: lookup SDCA version and functions
  ASoC: SDCA: add quirk function for RT712_VB match
  ASoC: rt712-sdca: detect the SMART_MIC function during the probe stage
  ASoC: soc-acpi: introduce new 'machine check' callback
  ASoC: sdw_utils: add SmartMic DAI for RT712 VB
  ASoC: sdw_utils: add SmartMic DAI for RT713 VB
  ASoC: Intel: soc-acpi: add is_device_rt712_vb() helper
  ASoC: SOF: Intel: hda: use machine_check() for SoundWire

 drivers/soundwire/Kconfig                     |   1 +
 drivers/soundwire/amd_init.c                  |  12 +-
 drivers/soundwire/intel_init.c                |  13 +-
 drivers/soundwire/slave.c                     |  14 ++
 include/linux/soundwire/sdw.h                 |   9 +-
 include/linux/soundwire/sdw_amd.h             |   7 +-
 include/linux/soundwire/sdw_intel.h           |   8 +-
 include/sound/sdca.h                          |  62 +++++++
 include/sound/sdca_function.h                 |  55 ++++++
 include/sound/soc-acpi.h                      |   8 +-
 sound/soc/Kconfig                             |   1 +
 sound/soc/Makefile                            |   1 +
 sound/soc/amd/ps/pci-ps.c                     |   3 +-
 sound/soc/codecs/rt712-sdca-sdw.c             |   1 +
 sound/soc/codecs/rt712-sdca.c                 |  38 +++-
 sound/soc/codecs/rt712-sdca.h                 |   1 +
 sound/soc/intel/Kconfig                       |   5 +
 sound/soc/intel/common/Makefile               |   3 +
 .../intel/common/soc-acpi-intel-mtl-match.c   |  51 ++++++
 .../intel/common/soc-acpi-intel-sdca-quirks.c |  42 +++++
 .../intel/common/soc-acpi-intel-sdca-quirks.h |  14 ++
 sound/soc/sdca/Kconfig                        |  11 ++
 sound/soc/sdca/Makefile                       |   5 +
 sound/soc/sdca/sdca_device.c                  |  67 +++++++
 sound/soc/sdca/sdca_functions.c               | 173 ++++++++++++++++++
 sound/soc/sdw_utils/soc_sdw_utils.c           |  18 +-
 sound/soc/soc-acpi.c                          |  30 +--
 sound/soc/sof/amd/acp-common.c                |   3 +-
 sound/soc/sof/intel/hda.c                     |  19 +-
 29 files changed, 610 insertions(+), 65 deletions(-)
 create mode 100644 include/sound/sdca.h
 create mode 100644 include/sound/sdca_function.h
 create mode 100644 sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
 create mode 100644 sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h
 create mode 100644 sound/soc/sdca/Kconfig
 create mode 100644 sound/soc/sdca/Makefile
 create mode 100644 sound/soc/sdca/sdca_device.c
 create mode 100644 sound/soc/sdca/sdca_functions.c

-- 
2.43.0


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

* [PATCH 01/11] soundwire: sdw_intel: include linux/acpi.h
  2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
@ 2024-10-16 10:23 ` Bard Liao
  2024-10-17 12:23   ` Vinod Koul
  2024-10-16 10:23 ` [PATCH 02/11] ASoC/soundwire: remove sdw_slave_extended_id Bard Liao
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 15+ messages in thread
From: Bard Liao @ 2024-10-16 10:23 UTC (permalink / raw)
  To: broonie, tiwai, vkoul
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

For the acpi_handle stuff.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
---
 include/linux/soundwire/sdw_intel.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h
index 37ae69365fe2..fae345987b8c 100644
--- a/include/linux/soundwire/sdw_intel.h
+++ b/include/linux/soundwire/sdw_intel.h
@@ -4,6 +4,7 @@
 #ifndef __SDW_INTEL_H
 #define __SDW_INTEL_H
 
+#include <linux/acpi.h>
 #include <linux/irqreturn.h>
 #include <linux/soundwire/sdw.h>
 
-- 
2.43.0


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

* [PATCH 02/11] ASoC/soundwire: remove sdw_slave_extended_id
  2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
  2024-10-16 10:23 ` [PATCH 01/11] soundwire: sdw_intel: include linux/acpi.h Bard Liao
@ 2024-10-16 10:23 ` Bard Liao
  2024-10-16 10:23 ` [PATCH 03/11] ASoC: SDCA: add initial module Bard Liao
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Bard Liao @ 2024-10-16 10:23 UTC (permalink / raw)
  To: broonie, tiwai, vkoul
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

This structure is used to copy information from the 'sdw_slave'
structures, it's better to create a flexible array of 'sdw_slave'
pointers and directly access the information. This will also help
access additional information stored in the 'sdw_slave' structure,
such as an SDCA context.

This patch does not add new functionality, it only modified how the
information is retrieved.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 drivers/soundwire/amd_init.c        | 12 ++++++------
 drivers/soundwire/intel_init.c      | 13 ++++++-------
 include/linux/soundwire/sdw.h       |  6 +++---
 include/linux/soundwire/sdw_amd.h   |  7 ++-----
 include/linux/soundwire/sdw_intel.h |  7 ++-----
 include/sound/soc-acpi.h            |  3 +--
 sound/soc/amd/ps/pci-ps.c           |  3 +--
 sound/soc/soc-acpi.c                | 30 +++++++++++++++--------------
 sound/soc/sof/amd/acp-common.c      |  3 +--
 sound/soc/sof/intel/hda.c           | 16 ++++++++-------
 10 files changed, 47 insertions(+), 53 deletions(-)

diff --git a/drivers/soundwire/amd_init.c b/drivers/soundwire/amd_init.c
index db040f435059..53d1d707ca1a 100644
--- a/drivers/soundwire/amd_init.c
+++ b/drivers/soundwire/amd_init.c
@@ -177,7 +177,7 @@ EXPORT_SYMBOL_NS(sdw_amd_probe, SOUNDWIRE_AMD_INIT);
 void sdw_amd_exit(struct sdw_amd_ctx *ctx)
 {
 	sdw_amd_cleanup(ctx);
-	kfree(ctx->ids);
+	kfree(ctx->peripherals);
 	kfree(ctx);
 }
 EXPORT_SYMBOL_NS(sdw_amd_exit, SOUNDWIRE_AMD_INIT);
@@ -204,10 +204,11 @@ int sdw_amd_get_slave_info(struct sdw_amd_ctx *ctx)
 			num_slaves++;
 	}
 
-	ctx->ids = kcalloc(num_slaves, sizeof(*ctx->ids), GFP_KERNEL);
-	if (!ctx->ids)
+	ctx->peripherals = kmalloc(struct_size(ctx->peripherals, array, num_slaves),
+				   GFP_KERNEL);
+	if (!ctx->peripherals)
 		return -ENOMEM;
-	ctx->num_slaves = num_slaves;
+	ctx->peripherals->num_peripherals = num_slaves;
 	for (index = 0; index < ctx->count; index++) {
 		if (!(ctx->link_mask & BIT(index)))
 			continue;
@@ -215,8 +216,7 @@ int sdw_amd_get_slave_info(struct sdw_amd_ctx *ctx)
 		if (amd_manager) {
 			bus = &amd_manager->bus;
 			list_for_each_entry(slave, &bus->slaves, node) {
-				ctx->ids[i].id = slave->id;
-				ctx->ids[i].link_id = bus->link_id;
+				ctx->peripherals->array[i] = slave;
 				i++;
 			}
 		}
diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c
index a09134b97cd6..12e7a98f319f 100644
--- a/drivers/soundwire/intel_init.c
+++ b/drivers/soundwire/intel_init.c
@@ -252,17 +252,16 @@ static struct sdw_intel_ctx
 			num_slaves++;
 	}
 
-	ctx->ids = kcalloc(num_slaves, sizeof(*ctx->ids), GFP_KERNEL);
-	if (!ctx->ids)
+	ctx->peripherals = kmalloc(struct_size(ctx->peripherals, array, num_slaves),
+				   GFP_KERNEL);
+	if (!ctx->peripherals)
 		goto err;
-
-	ctx->num_slaves = num_slaves;
+	ctx->peripherals->num_peripherals = num_slaves;
 	i = 0;
 	list_for_each_entry(link, &ctx->link_list, list) {
 		bus = &link->cdns->bus;
 		list_for_each_entry(slave, &bus->slaves, node) {
-			ctx->ids[i].id = slave->id;
-			ctx->ids[i].link_id = bus->link_id;
+			ctx->peripherals->array[i] = slave;
 			i++;
 		}
 	}
@@ -371,7 +370,7 @@ void sdw_intel_exit(struct sdw_intel_ctx *ctx)
 	}
 
 	sdw_intel_cleanup(ctx);
-	kfree(ctx->ids);
+	kfree(ctx->peripherals);
 	kfree(ctx->ldev);
 	kfree(ctx);
 }
diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h
index 5e0dd47a0412..283c8bfdde49 100644
--- a/include/linux/soundwire/sdw.h
+++ b/include/linux/soundwire/sdw.h
@@ -488,9 +488,9 @@ struct sdw_slave_id {
 	__u8 sdw_version:4;
 };
 
-struct sdw_extended_slave_id {
-	int link_id;
-	struct sdw_slave_id id;
+struct sdw_peripherals {
+	int num_peripherals;
+	struct sdw_slave *array[];
 };
 
 /*
diff --git a/include/linux/soundwire/sdw_amd.h b/include/linux/soundwire/sdw_amd.h
index 28a4eb77717f..585b4c58a8a6 100644
--- a/include/linux/soundwire/sdw_amd.h
+++ b/include/linux/soundwire/sdw_amd.h
@@ -115,19 +115,16 @@ struct sdw_amd_acpi_info {
  * struct sdw_amd_ctx - context allocated by the controller driver probe
  *
  * @count: link count
- * @num_slaves: total number of devices exposed across all enabled links
  * @link_mask: bit-wise mask listing SoundWire links reported by the
  * Controller
- * @ids: array of slave_id, representing Slaves exposed across all enabled
- * links
  * @pdev: platform device structure
+ * @peripherals: array representing Peripherals exposed across all enabled links
  */
 struct sdw_amd_ctx {
 	int count;
-	int num_slaves;
 	u32 link_mask;
-	struct sdw_extended_slave_id *ids;
 	struct platform_device *pdev[AMD_SDW_MAX_MANAGER_COUNT];
+	struct sdw_peripherals *peripherals;
 };
 
 /**
diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h
index fae345987b8c..491ddd27270f 100644
--- a/include/linux/soundwire/sdw_intel.h
+++ b/include/linux/soundwire/sdw_intel.h
@@ -287,31 +287,28 @@ struct hdac_bus;
  * hardware capabilities after all power dependencies are settled.
  * @link_mask: bit-wise mask listing SoundWire links reported by the
  * Controller
- * @num_slaves: total number of devices exposed across all enabled links
  * @handle: ACPI parent handle
  * @ldev: information for each link (controller-specific and kept
  * opaque here)
- * @ids: array of slave_id, representing Slaves exposed across all enabled
- * links
  * @link_list: list to handle interrupts across all links
  * @shim_lock: mutex to handle concurrent rmw access to shared SHIM registers.
  * @shim_mask: flags to track initialization of SHIM shared registers
  * @shim_base: sdw shim base.
  * @alh_base: sdw alh base.
+ * @peripherals: array representing Peripherals exposed across all enabled links
  */
 struct sdw_intel_ctx {
 	int count;
 	void __iomem *mmio_base;
 	u32 link_mask;
-	int num_slaves;
 	acpi_handle handle;
 	struct sdw_intel_link_dev **ldev;
-	struct sdw_extended_slave_id *ids;
 	struct list_head link_list;
 	struct mutex shim_lock; /* lock for access to shared SHIM registers */
 	u32 shim_mask;
 	u32 shim_base;
 	u32 alh_base;
+	struct sdw_peripherals *peripherals;
 };
 
 /**
diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h
index 60d3b86a4660..ac7f9e791ee1 100644
--- a/include/sound/soc-acpi.h
+++ b/include/sound/soc-acpi.h
@@ -233,7 +233,6 @@ static inline bool snd_soc_acpi_sof_parent(struct device *dev)
 
 bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev,
 					const struct snd_soc_acpi_link_adr *link,
-					struct sdw_extended_slave_id *ids,
-					int num_slaves);
+					struct sdw_peripherals *peripherals);
 
 #endif
diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c
index c72d666d51bd..4365499c8f82 100644
--- a/sound/soc/amd/ps/pci-ps.c
+++ b/sound/soc/amd/ps/pci-ps.c
@@ -302,8 +302,7 @@ static struct snd_soc_acpi_mach *acp63_sdw_machine_select(struct device *dev)
 			link = mach->links;
 			for (i = 0; i < acp_data->info.count && link->num_adr; link++, i++) {
 				if (!snd_soc_acpi_sdw_link_slaves_found(dev, link,
-									acp_data->sdw->ids,
-									acp_data->sdw->num_slaves))
+									acp_data->sdw->peripherals))
 					break;
 			}
 			if (i == acp_data->info.count || !link->num_adr)
diff --git a/sound/soc/soc-acpi.c b/sound/soc/soc-acpi.c
index 6d693b2ad5a3..270f9777942f 100644
--- a/sound/soc/soc-acpi.c
+++ b/sound/soc/soc-acpi.c
@@ -131,8 +131,7 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_codec_list);
 /* Check if all Slaves defined on the link can be found */
 bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev,
 					const struct snd_soc_acpi_link_adr *link,
-					struct sdw_extended_slave_id *ids,
-					int num_slaves)
+					struct sdw_peripherals *peripherals)
 {
 	unsigned int part_id, link_id, unique_id, mfg_id, version;
 	int i, j, k;
@@ -146,22 +145,25 @@ bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev,
 		link_id = SDW_DISCO_LINK_ID(adr);
 		version = SDW_VERSION(adr);
 
-		for (j = 0; j < num_slaves; j++) {
+		for (j = 0; j < peripherals->num_peripherals; j++) {
+			struct sdw_slave *peripheral = peripherals->array[j];
+
 			/* find out how many identical parts were reported on that link */
-			if (ids[j].link_id == link_id &&
-			    ids[j].id.part_id == part_id &&
-			    ids[j].id.mfg_id == mfg_id &&
-			    ids[j].id.sdw_version == version)
+			if (peripheral->bus->link_id == link_id &&
+			    peripheral->id.part_id == part_id &&
+			    peripheral->id.mfg_id == mfg_id &&
+			    peripheral->id.sdw_version == version)
 				reported_part_count++;
 		}
 
-		for (j = 0; j < num_slaves; j++) {
+		for (j = 0; j < peripherals->num_peripherals; j++) {
+			struct sdw_slave *peripheral = peripherals->array[j];
 			int expected_part_count = 0;
 
-			if (ids[j].link_id != link_id ||
-			    ids[j].id.part_id != part_id ||
-			    ids[j].id.mfg_id != mfg_id ||
-			    ids[j].id.sdw_version != version)
+			if (peripheral->bus->link_id != link_id ||
+			    peripheral->id.part_id != part_id ||
+			    peripheral->id.mfg_id != mfg_id ||
+			    peripheral->id.sdw_version != version)
 				continue;
 
 			/* find out how many identical parts are expected */
@@ -180,7 +182,7 @@ bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev,
 				 */
 				unique_id = SDW_UNIQUE_ID(adr);
 				if (reported_part_count == 1 ||
-				    ids[j].id.unique_id == unique_id) {
+				    peripheral->id.unique_id == unique_id) {
 					dev_dbg(dev, "found part_id %#x at link %d\n", part_id, link_id);
 					break;
 				}
@@ -189,7 +191,7 @@ bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev,
 					part_id, reported_part_count, expected_part_count, link_id);
 			}
 		}
-		if (j == num_slaves) {
+		if (j == peripherals->num_peripherals) {
 			dev_dbg(dev, "Slave part_id %#x not found\n", part_id);
 			return false;
 		}
diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c
index dbcaac84cb73..fc792956bb97 100644
--- a/sound/soc/sof/amd/acp-common.c
+++ b/sound/soc/sof/amd/acp-common.c
@@ -145,8 +145,7 @@ static struct snd_soc_acpi_mach *amd_sof_sdw_machine_select(struct snd_sof_dev *
 			link = mach->links;
 			for (i = 0; i < acp_data->info.count && link->num_adr; link++, i++) {
 				if (!snd_soc_acpi_sdw_link_slaves_found(sdev->dev, link,
-									acp_data->sdw->ids,
-									acp_data->sdw->num_slaves))
+									acp_data->sdw->peripherals))
 					break;
 			}
 			if (i == acp_data->info.count || !link->num_adr)
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index e4cb4ffc7270..9abc4c071ae5 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -1064,7 +1064,7 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
 {
 	struct snd_sof_pdata *pdata = sdev->pdata;
 	const struct snd_soc_acpi_link_adr *link;
-	struct sdw_extended_slave_id *ids;
+	struct sdw_peripherals *peripherals;
 	struct snd_soc_acpi_mach *mach;
 	struct sof_intel_hda_dev *hdev;
 	u32 link_mask;
@@ -1083,7 +1083,7 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
 		return NULL;
 	}
 
-	if (!hdev->sdw->num_slaves) {
+	if (!hdev->sdw->peripherals || !hdev->sdw->peripherals->num_peripherals) {
 		dev_warn(sdev->dev, "No SoundWire peripheral detected in ACPI tables\n");
 		return NULL;
 	}
@@ -1119,8 +1119,7 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
 			 * are not found on this link.
 			 */
 			if (!snd_soc_acpi_sdw_link_slaves_found(sdev->dev, link,
-								hdev->sdw->ids,
-								hdev->sdw->num_slaves))
+								hdev->sdw->peripherals))
 				break;
 		}
 		/* Found if all Slaves are checked */
@@ -1136,10 +1135,13 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
 	}
 
 	dev_info(sdev->dev, "No SoundWire machine driver found for the ACPI-reported configuration:\n");
-	ids = hdev->sdw->ids;
-	for (i = 0; i < hdev->sdw->num_slaves; i++)
+	peripherals = hdev->sdw->peripherals;
+	for (i = 0; i < peripherals->num_peripherals; i++)
 		dev_info(sdev->dev, "link %d mfg_id 0x%04x part_id 0x%04x version %#x\n",
-			 ids[i].link_id, ids[i].id.mfg_id, ids[i].id.part_id, ids[i].id.sdw_version);
+			 peripherals->array[i]->bus->link_id,
+			 peripherals->array[i]->id.mfg_id,
+			 peripherals->array[i]->id.part_id,
+			 peripherals->array[i]->id.sdw_version);
 
 	return NULL;
 }
-- 
2.43.0


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

* [PATCH 03/11] ASoC: SDCA: add initial module
  2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
  2024-10-16 10:23 ` [PATCH 01/11] soundwire: sdw_intel: include linux/acpi.h Bard Liao
  2024-10-16 10:23 ` [PATCH 02/11] ASoC/soundwire: remove sdw_slave_extended_id Bard Liao
@ 2024-10-16 10:23 ` Bard Liao
  2024-10-16 10:23 ` [PATCH 04/11] soundwire: slave: lookup SDCA version and functions Bard Liao
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Bard Liao @ 2024-10-16 10:23 UTC (permalink / raw)
  To: broonie, tiwai, vkoul
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

Add new module for SDCA (SoundWire Device Class for Audio) support.
For now just add a parser to identify the SDCA revision and the
function mask.

Note that the SDCA definitions and related MIPI DisCo properties are
defined only for ACPI platforms and extracted with _DSD helpers. There
is currently no support for Device Tree in the specification, the
'depends on ACPI' reflects this design limitation. This might change
in a future revision of the specification but for SDCA 1.0 ACPI is the
only supported type of platform firmware.

The SDCA library is defined with static inline fallbacks, which will
allow for unconditional addition of SDCA support in common parts of
the code.

The design follows a four-step process:

1) Basic information related to Functions is extracted from MIPI DisCo
tables and stored in the 'struct sdw_slave'. Devm_ based memory
allocation is not allowed at this point prior to a driver probe, so we only
store the function node, address and type.

2) When a codec driver probes, it will register subdevices for each
Function identified in phase 1)

3) a driver will probe for each subdevice and addition parsing/memory
allocation takes place at this level. devm_ based allocation is highly
encouraged to make error handling manageable.

4) Before the peripheral device becomes physically attached, register
access is not permitted and the regmaps are cache-only. When
peripheral device is enumerated, the bus level uses the
'update_status' notification; after optional device-level
initialization, the codec driver will notify each of the subdevices so
that they can start interacting with the hardware.

Note that the context extracted in 1) should be arguably be handled
completely in the codec driver probe. That would however make it
difficult to use the ACPI information for machine quirks, and
e.g. select different machine driver and topologies as done for the
RT712_VB handling later in the series. To make the implementation of
quirks simpler, this patchset extracts a minimal amount of context
(interface revision and number/type of Functions) before the codec
driver probe, and stores this context in the scope of the 'struct
sdw_slave'.

The SDCA library can also be used in a vendor-specific driver without
creating subdevices, e.g. to retrieve the 'initialization-table'
values to write platform-specific values as needed.

For more technical details, the SDCA specification is available for
public downloads at https://www.mipi.org/mipi-sdca-v1-0-download

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 include/linux/soundwire/sdw.h   |   3 +
 include/sound/sdca.h            |  54 ++++++++++
 include/sound/sdca_function.h   |  55 ++++++++++
 sound/soc/Kconfig               |   1 +
 sound/soc/Makefile              |   1 +
 sound/soc/sdca/Kconfig          |  11 ++
 sound/soc/sdca/Makefile         |   5 +
 sound/soc/sdca/sdca_device.c    |  24 +++++
 sound/soc/sdca/sdca_functions.c | 173 ++++++++++++++++++++++++++++++++
 9 files changed, 327 insertions(+)
 create mode 100644 include/sound/sdca.h
 create mode 100644 include/sound/sdca_function.h
 create mode 100644 sound/soc/sdca/Kconfig
 create mode 100644 sound/soc/sdca/Makefile
 create mode 100644 sound/soc/sdca/sdca_device.c
 create mode 100644 sound/soc/sdca/sdca_functions.c

diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h
index 283c8bfdde49..49d690f3d29a 100644
--- a/include/linux/soundwire/sdw.h
+++ b/include/linux/soundwire/sdw.h
@@ -10,6 +10,7 @@
 #include <linux/irqdomain.h>
 #include <linux/mod_devicetable.h>
 #include <linux/bitfield.h>
+#include <sound/sdca.h>
 
 struct sdw_bus;
 struct sdw_slave;
@@ -663,6 +664,7 @@ struct sdw_slave_ops {
  * @is_mockup_device: status flag used to squelch errors in the command/control
  * protocol for SoundWire mockup devices
  * @sdw_dev_lock: mutex used to protect callbacks/remove races
+ * @sdca_data: structure containing all device data for SDCA helpers
  */
 struct sdw_slave {
 	struct sdw_slave_id id;
@@ -686,6 +688,7 @@ struct sdw_slave {
 	bool first_interrupt_done;
 	bool is_mockup_device;
 	struct mutex sdw_dev_lock; /* protect callbacks/remove races */
+	struct sdca_device_data sdca_data;
 };
 
 #define dev_to_sdw_dev(_dev) container_of(_dev, struct sdw_slave, dev)
diff --git a/include/sound/sdca.h b/include/sound/sdca.h
new file mode 100644
index 000000000000..34473ca4c789
--- /dev/null
+++ b/include/sound/sdca.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
+/*
+ * The MIPI SDCA specification is available for public downloads at
+ * https://www.mipi.org/mipi-sdca-v1-0-download
+ *
+ * Copyright(c) 2024 Intel Corporation
+ */
+
+#ifndef __SDCA_H__
+#define __SDCA_H__
+
+struct sdw_slave;
+
+#define SDCA_MAX_FUNCTION_COUNT 8
+
+/**
+ * sdca_device_desc - short descriptor for an SDCA Function
+ * @adr: ACPI address (used for SDCA register access)
+ * @type: Function topology type
+ * @name: human-readable string
+ */
+struct sdca_function_desc {
+	u64 adr;
+	u32 type;
+	const char *name;
+};
+
+/**
+ * sdca_device_data - structure containing all SDCA related information
+ * @sdca_interface_revision: value read from _DSD property, mainly to check
+ * for changes between silicon versions
+ * @num_functions: total number of supported SDCA functions. Invalid/unsupported
+ * functions will be skipped.
+ * @sdca_func: array of function descriptors
+ */
+struct sdca_device_data {
+	u32 interface_revision;
+	int num_functions;
+	struct sdca_function_desc sdca_func[SDCA_MAX_FUNCTION_COUNT];
+};
+
+#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA)
+
+void sdca_lookup_functions(struct sdw_slave *slave);
+void sdca_lookup_interface_revision(struct sdw_slave *slave);
+
+#else
+
+static inline void sdca_lookup_functions(struct sdw_slave *slave) {}
+static inline void sdca_lookup_interface_revision(struct sdw_slave *slave) {}
+
+#endif
+
+#endif
diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h
new file mode 100644
index 000000000000..a01eec86b9a6
--- /dev/null
+++ b/include/sound/sdca_function.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
+/*
+ * The MIPI SDCA specification is available for public downloads at
+ * https://www.mipi.org/mipi-sdca-v1-0-download
+ *
+ * Copyright(c) 2024 Intel Corporation
+ */
+
+#ifndef __SDCA_FUNCTION_H__
+#define __SDCA_FUNCTION_H__
+
+/*
+ * SDCA Function Types from SDCA specification v1.0a Section 5.1.2
+ * all Function types not described are reserved
+ * Note that SIMPLE_AMP, SIMPLE_MIC and SIMPLE_JACK Function Types
+ * are NOT defined in SDCA 1.0a, but they were defined in earlier
+ * drafts and are planned for 1.1.
+ */
+
+enum sdca_function_type {
+	SDCA_FUNCTION_TYPE_SMART_AMP	= 0x01,	/* Amplifier with protection features */
+	SDCA_FUNCTION_TYPE_SIMPLE_AMP	= 0x02,	/* subset of SmartAmp */
+	SDCA_FUNCTION_TYPE_SMART_MIC	= 0x03,	/* Smart microphone with acoustic triggers */
+	SDCA_FUNCTION_TYPE_SIMPLE_MIC	= 0x04,	/* subset of SmartMic */
+	SDCA_FUNCTION_TYPE_SPEAKER_MIC	= 0x05,	/* Combination of SmartMic and SmartAmp */
+	SDCA_FUNCTION_TYPE_UAJ		= 0x06,	/* 3.5mm Universal Audio jack */
+	SDCA_FUNCTION_TYPE_RJ		= 0x07,	/* Retaskable jack */
+	SDCA_FUNCTION_TYPE_SIMPLE_JACK	= 0x08,	/* Subset of UAJ */
+	SDCA_FUNCTION_TYPE_HID		= 0x0A,	/* Human Interface Device, for e.g. buttons */
+	SDCA_FUNCTION_TYPE_IMP_DEF	= 0x1F,	/* Implementation-defined function */
+};
+
+/* Human-readable names used for kernel logs and Function device registration/bind */
+#define	SDCA_FUNCTION_TYPE_SMART_AMP_NAME	"SmartAmp"
+#define	SDCA_FUNCTION_TYPE_SIMPLE_AMP_NAME	"SimpleAmp"
+#define	SDCA_FUNCTION_TYPE_SMART_MIC_NAME	"SmartMic"
+#define	SDCA_FUNCTION_TYPE_SIMPLE_MIC_NAME	"SimpleMic"
+#define	SDCA_FUNCTION_TYPE_SPEAKER_MIC_NAME	"SpeakerMic"
+#define	SDCA_FUNCTION_TYPE_UAJ_NAME		"UAJ"
+#define	SDCA_FUNCTION_TYPE_RJ_NAME		"RJ"
+#define	SDCA_FUNCTION_TYPE_SIMPLE_NAME		"SimpleJack"
+#define	SDCA_FUNCTION_TYPE_HID_NAME		"HID"
+
+enum sdca_entity0_controls {
+	SDCA_CONTROL_ENTITY_0_COMMIT_GROUP_MASK		= 0x01,
+	SDCA_CONTROL_ENTITY_0_INTSTAT_CLEAR		= 0x02,
+	SDCA_CONTROL_ENTITY_0_INT_ENABLE		= 0x03,
+	SDCA_CONTROL_ENTITY_0_FUNCTION_SDCA_VERSION	= 0x04,
+	SDCA_CONTROL_ENTITY_0_FUNCTION_TOPOLOGY		= 0x05,
+	SDCA_CONTROL_ENTITY_0_FUNCTION_MANUFACTURER_ID	= 0x06,
+	SDCA_CONTROL_ENTITY_0_FUNCTION_ID		= 0x07,
+	SDCA_CONTROL_ENTITY_0_FUNCTION_VERSION		= 0x08
+};
+
+#endif
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index e87bd15a8b43..8e01b421fe8d 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -108,6 +108,7 @@ source "sound/soc/pxa/Kconfig"
 source "sound/soc/qcom/Kconfig"
 source "sound/soc/rockchip/Kconfig"
 source "sound/soc/samsung/Kconfig"
+source "sound/soc/sdca/Kconfig"
 source "sound/soc/sh/Kconfig"
 source "sound/soc/sof/Kconfig"
 source "sound/soc/spear/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 775bb38c2ed4..5307b0b62a93 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_SND_SOC)	+= pxa/
 obj-$(CONFIG_SND_SOC)	+= qcom/
 obj-$(CONFIG_SND_SOC)	+= rockchip/
 obj-$(CONFIG_SND_SOC)	+= samsung/
+obj-$(CONFIG_SND_SOC)	+= sdca/
 obj-$(CONFIG_SND_SOC)	+= sh/
 obj-$(CONFIG_SND_SOC)	+= sof/
 obj-$(CONFIG_SND_SOC)	+= spear/
diff --git a/sound/soc/sdca/Kconfig b/sound/soc/sdca/Kconfig
new file mode 100644
index 000000000000..07f6822fa614
--- /dev/null
+++ b/sound/soc/sdca/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config SND_SOC_SDCA
+	tristate "ASoC SDCA library"
+	depends on ACPI
+	help
+	  This option enables support for the MIPI SoundWire Device
+	  Class for Audio (SDCA).
+
+config SND_SOC_SDCA_OPTIONAL
+	def_tristate SND_SOC_SDCA || !SND_SOC_SDCA
diff --git a/sound/soc/sdca/Makefile b/sound/soc/sdca/Makefile
new file mode 100644
index 000000000000..c296bd5a0a7c
--- /dev/null
+++ b/sound/soc/sdca/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+snd-soc-sdca-objs	:= sdca_functions.o sdca_device.o
+
+obj-$(CONFIG_SND_SOC_SDCA)	+= snd-soc-sdca.o
diff --git a/sound/soc/sdca/sdca_device.c b/sound/soc/sdca/sdca_device.c
new file mode 100644
index 000000000000..58f5f6f0f723
--- /dev/null
+++ b/sound/soc/sdca/sdca_device.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2024 Intel Corporation
+
+/*
+ * The MIPI SDCA specification is available for public downloads at
+ * https://www.mipi.org/mipi-sdca-v1-0-download
+ */
+
+#include <linux/acpi.h>
+#include <linux/soundwire/sdw.h>
+#include <sound/sdca.h>
+
+void sdca_lookup_interface_revision(struct sdw_slave *slave)
+{
+	struct fwnode_handle *fwnode = slave->dev.fwnode;
+
+	/*
+	 * if this property is not present, then the sdca_interface_revision will
+	 * remain zero, which will be considered as 'not defined' or 'invalid'.
+	 */
+	fwnode_property_read_u32(fwnode, "mipi-sdw-sdca-interface-revision",
+				 &slave->sdca_data.interface_revision);
+}
+EXPORT_SYMBOL_NS(sdca_lookup_interface_revision, SND_SOC_SDCA);
diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c
new file mode 100644
index 000000000000..a6ad57430dd4
--- /dev/null
+++ b/sound/soc/sdca/sdca_functions.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2024 Intel Corporation
+
+/*
+ * The MIPI SDCA specification is available for public downloads at
+ * https://www.mipi.org/mipi-sdca-v1-0-download
+ */
+
+#include <linux/acpi.h>
+#include <linux/soundwire/sdw.h>
+#include <sound/sdca.h>
+#include <sound/sdca_function.h>
+
+static int patch_sdca_function_type(struct device *dev,
+				    u32 interface_revision,
+				    u32 *function_type,
+				    const char **function_name)
+{
+	unsigned long function_type_patch = 0;
+
+	/*
+	 * Unfortunately early SDCA specifications used different indices for Functions,
+	 * for backwards compatibility we have to reorder the values found
+	 */
+	if (interface_revision >= 0x0801)
+		goto skip_early_draft_order;
+
+	switch (*function_type) {
+	case 1:
+		function_type_patch = SDCA_FUNCTION_TYPE_SMART_AMP;
+		break;
+	case 2:
+		function_type_patch = SDCA_FUNCTION_TYPE_SMART_MIC;
+		break;
+	case 3:
+		function_type_patch = SDCA_FUNCTION_TYPE_SPEAKER_MIC;
+		break;
+	case 4:
+		function_type_patch = SDCA_FUNCTION_TYPE_UAJ;
+		break;
+	case 5:
+		function_type_patch = SDCA_FUNCTION_TYPE_RJ;
+		break;
+	case 6:
+		function_type_patch = SDCA_FUNCTION_TYPE_HID;
+		break;
+	default:
+		dev_warn(dev, "%s: SDCA version %#x unsupported function type %d, skipped\n",
+			 __func__, interface_revision, *function_type);
+		return -EINVAL;
+	}
+
+skip_early_draft_order:
+	if (function_type_patch)
+		*function_type = function_type_patch;
+
+	/* now double-check the values */
+	switch (*function_type) {
+	case SDCA_FUNCTION_TYPE_SMART_AMP:
+		*function_name = SDCA_FUNCTION_TYPE_SMART_AMP_NAME;
+		break;
+	case SDCA_FUNCTION_TYPE_SMART_MIC:
+		*function_name = SDCA_FUNCTION_TYPE_SMART_MIC_NAME;
+		break;
+	case SDCA_FUNCTION_TYPE_UAJ:
+		*function_name = SDCA_FUNCTION_TYPE_UAJ_NAME;
+		break;
+	case SDCA_FUNCTION_TYPE_HID:
+		*function_name = SDCA_FUNCTION_TYPE_HID_NAME;
+		break;
+	case SDCA_FUNCTION_TYPE_SIMPLE_AMP:
+	case SDCA_FUNCTION_TYPE_SIMPLE_MIC:
+	case SDCA_FUNCTION_TYPE_SPEAKER_MIC:
+	case SDCA_FUNCTION_TYPE_RJ:
+	case SDCA_FUNCTION_TYPE_IMP_DEF:
+		dev_warn(dev, "%s: found unsupported SDCA function type %d, skipped\n",
+			 __func__, *function_type);
+		return -EINVAL;
+	default:
+		dev_err(dev, "%s: found invalid SDCA function type %d, skipped\n",
+			__func__, *function_type);
+		return -EINVAL;
+	}
+
+	dev_info(dev, "%s: found SDCA function %s (type %d)\n",
+		 __func__, *function_name, *function_type);
+
+	return 0;
+}
+
+static int find_sdca_function(struct acpi_device *adev, void *data)
+{
+	struct fwnode_handle *function_node = acpi_fwnode_handle(adev);
+	struct sdca_device_data *sdca_data = data;
+	struct device *dev = &adev->dev;
+	struct fwnode_handle *control5; /* used to identify function type */
+	const char *function_name;
+	u32 function_type;
+	int func_index;
+	u64 addr;
+	int ret;
+
+	if (sdca_data->num_functions >= SDCA_MAX_FUNCTION_COUNT) {
+		dev_err(dev, "%s: maximum number of functions exceeded\n", __func__);
+		return -EINVAL;
+	}
+
+	/*
+	 * The number of functions cannot exceed 8, we could use
+	 * acpi_get_local_address() but the value is stored as u64 so
+	 * we might as well avoid casts and intermediate levels
+	 */
+	ret = acpi_get_local_u64_address(adev->handle, &addr);
+	if (ret < 0)
+		return ret;
+
+	if (!addr) {
+		dev_err(dev, "%s: no addr\n", __func__);
+		return -ENODEV;
+	}
+
+	/*
+	 * Extracting the topology type for an SDCA function is a
+	 * convoluted process.
+	 * The Function type is only visible as a result of a read
+	 * from a control. In theory this would mean reading from the hardware,
+	 * but the SDCA/DisCo specs defined the notion of "DC value" - a constant
+	 * represented with a DSD subproperty.
+	 * Drivers have to query the properties for the control
+	 * SDCA_CONTROL_ENTITY_0_FUNCTION_TOPOLOGY (0x05)
+	 */
+	control5 = fwnode_get_named_child_node(function_node,
+					       "mipi-sdca-control-0x5-subproperties");
+	if (!control5)
+		return -ENODEV;
+
+	ret = fwnode_property_read_u32(control5, "mipi-sdca-control-dc-value",
+				       &function_type);
+
+	fwnode_handle_put(control5);
+
+	if (ret < 0) {
+		dev_err(dev, "%s: the function type can only be determined from ACPI information\n",
+			__func__);
+		return ret;
+	}
+
+	ret = patch_sdca_function_type(dev, sdca_data->interface_revision,
+				       &function_type, &function_name);
+	if (ret < 0)
+		return ret;
+
+	/* store results */
+	func_index = sdca_data->num_functions;
+	sdca_data->sdca_func[func_index].adr = addr;
+	sdca_data->sdca_func[func_index].type = function_type;
+	sdca_data->sdca_func[func_index].name = function_name;
+	sdca_data->num_functions++;
+
+	return 0;
+}
+
+void sdca_lookup_functions(struct sdw_slave *slave)
+{
+	struct device *dev = &slave->dev;
+	struct acpi_device *adev = to_acpi_device_node(dev->fwnode);
+
+	acpi_dev_for_each_child(adev, find_sdca_function, &slave->sdca_data);
+}
+EXPORT_SYMBOL_NS(sdca_lookup_functions, SND_SOC_SDCA);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("SDCA library");
-- 
2.43.0


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

* [PATCH 04/11] soundwire: slave: lookup SDCA version and functions
  2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
                   ` (2 preceding siblings ...)
  2024-10-16 10:23 ` [PATCH 03/11] ASoC: SDCA: add initial module Bard Liao
@ 2024-10-16 10:23 ` Bard Liao
  2024-10-17 12:24   ` Vinod Koul
  2024-10-16 10:23 ` [PATCH 05/11] ASoC: SDCA: add quirk function for RT712_VB match Bard Liao
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 15+ messages in thread
From: Bard Liao @ 2024-10-16 10:23 UTC (permalink / raw)
  To: broonie, tiwai, vkoul
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

Use SDCA helpers to get the basic information and store it in the
slave context. The information will be optionally be used in codec
drivers to register sub-devices for each Function.

When platforms are not based on ACPI the helpers do absolutely
nothing.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 drivers/soundwire/Kconfig |  1 +
 drivers/soundwire/slave.c | 14 ++++++++++++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/soundwire/Kconfig b/drivers/soundwire/Kconfig
index 4d8f3b7024ae..f66f869dff2e 100644
--- a/drivers/soundwire/Kconfig
+++ b/drivers/soundwire/Kconfig
@@ -6,6 +6,7 @@
 menuconfig SOUNDWIRE
 	tristate "SoundWire support"
 	depends on ACPI || OF
+	depends on SND_SOC_SDCA_OPTIONAL
 	help
 	  SoundWire is a 2-Pin interface with data and clock line ratified
 	  by the MIPI Alliance. SoundWire is used for transporting data
diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c
index f1a4df6cfebd..97cf8bcca047 100644
--- a/drivers/soundwire/slave.c
+++ b/drivers/soundwire/slave.c
@@ -5,6 +5,7 @@
 #include <linux/of.h>
 #include <linux/soundwire/sdw.h>
 #include <linux/soundwire/sdw_type.h>
+#include <sound/sdca.h>
 #include "bus.h"
 #include "sysfs_local.h"
 
@@ -70,6 +71,17 @@ int sdw_slave_add(struct sdw_bus *bus,
 	list_add_tail(&slave->node, &bus->slaves);
 	mutex_unlock(&bus->bus_lock);
 
+	/*
+	 * The Soundwire driver probe may optionally register SDCA
+	 * sub-devices, one per Function. This means the information
+	 * on the SDCA revision and the number/type of Functions need
+	 * to be extracted from platform firmware before the SoundWire
+	 * driver probe, and as a consequence before the SoundWire
+	 * device_register() below.
+	 */
+	sdca_lookup_interface_revision(slave);
+	sdca_lookup_functions(slave);
+
 	ret = device_register(&slave->dev);
 	if (ret) {
 		dev_err(bus->dev, "Failed to add slave: ret %d\n", ret);
@@ -259,3 +271,5 @@ int sdw_of_find_slaves(struct sdw_bus *bus)
 
 	return 0;
 }
+
+MODULE_IMPORT_NS(SND_SOC_SDCA);
-- 
2.43.0


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

* [PATCH 05/11] ASoC: SDCA: add quirk function for RT712_VB match
  2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
                   ` (3 preceding siblings ...)
  2024-10-16 10:23 ` [PATCH 04/11] soundwire: slave: lookup SDCA version and functions Bard Liao
@ 2024-10-16 10:23 ` Bard Liao
  2024-10-16 10:23 ` [PATCH 06/11] ASoC: rt712-sdca: detect the SMART_MIC function during the probe stage Bard Liao
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Bard Liao @ 2024-10-16 10:23 UTC (permalink / raw)
  To: broonie, tiwai, vkoul
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

Add a generic match function for quirks, chances are we are going to
have lots of those...

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 include/sound/sdca.h         | 10 ++++++++-
 sound/soc/sdca/sdca_device.c | 43 ++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/include/sound/sdca.h b/include/sound/sdca.h
index 34473ca4c789..7e138229e8f3 100644
--- a/include/sound/sdca.h
+++ b/include/sound/sdca.h
@@ -39,16 +39,24 @@ struct sdca_device_data {
 	struct sdca_function_desc sdca_func[SDCA_MAX_FUNCTION_COUNT];
 };
 
+enum sdca_quirk {
+	SDCA_QUIRKS_RT712_VB,
+};
+
 #if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA)
 
 void sdca_lookup_functions(struct sdw_slave *slave);
 void sdca_lookup_interface_revision(struct sdw_slave *slave);
+bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk);
 
 #else
 
 static inline void sdca_lookup_functions(struct sdw_slave *slave) {}
 static inline void sdca_lookup_interface_revision(struct sdw_slave *slave) {}
-
+static inline bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk)
+{
+	return false;
+}
 #endif
 
 #endif
diff --git a/sound/soc/sdca/sdca_device.c b/sound/soc/sdca/sdca_device.c
index 58f5f6f0f723..c44dc21cb634 100644
--- a/sound/soc/sdca/sdca_device.c
+++ b/sound/soc/sdca/sdca_device.c
@@ -9,6 +9,7 @@
 #include <linux/acpi.h>
 #include <linux/soundwire/sdw.h>
 #include <sound/sdca.h>
+#include <sound/sdca_function.h>
 
 void sdca_lookup_interface_revision(struct sdw_slave *slave)
 {
@@ -22,3 +23,45 @@ void sdca_lookup_interface_revision(struct sdw_slave *slave)
 				 &slave->sdca_data.interface_revision);
 }
 EXPORT_SYMBOL_NS(sdca_lookup_interface_revision, SND_SOC_SDCA);
+
+static bool sdca_device_quirk_rt712_vb(struct sdw_slave *slave)
+{
+	struct sdw_slave_id *id = &slave->id;
+	int i;
+
+	/*
+	 * The RT712_VA relies on the v06r04 draft, and the
+	 * RT712_VB on a more recent v08r01 draft.
+	 */
+	if (slave->sdca_data.interface_revision < 0x0801)
+		return false;
+
+	if (id->mfg_id != 0x025d)
+		return false;
+
+	if (id->part_id != 0x712 &&
+	    id->part_id != 0x713 &&
+	    id->part_id != 0x716 &&
+	    id->part_id != 0x717)
+		return false;
+
+	for (i = 0; i < slave->sdca_data.num_functions; i++) {
+		if (slave->sdca_data.sdca_func[i].type ==
+		    SDCA_FUNCTION_TYPE_SMART_MIC)
+			return true;
+	}
+
+	return false;
+}
+
+bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk)
+{
+	switch (quirk) {
+	case SDCA_QUIRKS_RT712_VB:
+		return sdca_device_quirk_rt712_vb(slave);
+	default:
+		break;
+	}
+	return false;
+}
+EXPORT_SYMBOL_NS(sdca_device_quirk_match, SND_SOC_SDCA);
-- 
2.43.0


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

* [PATCH 06/11] ASoC: rt712-sdca: detect the SMART_MIC function during the probe stage
  2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
                   ` (4 preceding siblings ...)
  2024-10-16 10:23 ` [PATCH 05/11] ASoC: SDCA: add quirk function for RT712_VB match Bard Liao
@ 2024-10-16 10:23 ` Bard Liao
  2024-10-16 10:23 ` [PATCH 07/11] ASoC: soc-acpi: introduce new 'machine check' callback Bard Liao
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Bard Liao @ 2024-10-16 10:23 UTC (permalink / raw)
  To: broonie, tiwai, vkoul
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

We shouldn't do any devm_ based allocation in the io_init(), this need
to happen in the probe(). Luckily, we now have an SDCA helper to look
in ACPI tables if a SMART_MIC function is exposed.

FIXME: the registers are not well handled today, the regmap lists
registers which are not really supported in all platforms. The regmap
needs to throw an error if those registers are accessed without
existing.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 sound/soc/codecs/rt712-sdca-sdw.c |  1 +
 sound/soc/codecs/rt712-sdca.c     | 38 +++++++++++++++++++++++--------
 sound/soc/codecs/rt712-sdca.h     |  1 +
 3 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/sound/soc/codecs/rt712-sdca-sdw.c b/sound/soc/codecs/rt712-sdca-sdw.c
index 90d5aaddbd5b..549aa31faed4 100644
--- a/sound/soc/codecs/rt712-sdca-sdw.c
+++ b/sound/soc/codecs/rt712-sdca-sdw.c
@@ -507,3 +507,4 @@ module_sdw_driver(rt712_sdca_sdw_driver);
 MODULE_DESCRIPTION("ASoC RT712 SDCA SDW driver");
 MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SND_SOC_SDCA);
diff --git a/sound/soc/codecs/rt712-sdca.c b/sound/soc/codecs/rt712-sdca.c
index e210c574bb74..78dbf9eed494 100644
--- a/sound/soc/codecs/rt712-sdca.c
+++ b/sound/soc/codecs/rt712-sdca.c
@@ -18,6 +18,7 @@
 #include <linux/pm_runtime.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
+#include <sound/sdca.h>
 #include <linux/soundwire/sdw_registers.h>
 #include <linux/slab.h>
 #include <sound/soc-dapm.h>
@@ -1652,6 +1653,17 @@ int rt712_sdca_init(struct device *dev, struct regmap *regmap,
 	if (ret < 0)
 		return ret;
 
+	/* only add the dmic component if a SMART_MIC function is exposed in ACPI */
+	if (sdca_device_quirk_match(slave, SDCA_QUIRKS_RT712_VB)) {
+		ret =  devm_snd_soc_register_component(dev,
+						       &soc_sdca_dev_rt712_dmic,
+						       rt712_sdca_dmic_dai,
+						       ARRAY_SIZE(rt712_sdca_dmic_dai));
+		if (ret < 0)
+			return ret;
+		rt712->dmic_function_found = true;
+	}
+
 	/* set autosuspend parameters */
 	pm_runtime_set_autosuspend_delay(dev, 3000);
 	pm_runtime_use_autosuspend(dev);
@@ -1799,7 +1811,6 @@ static void rt712_sdca_vb_io_init(struct rt712_sdca_priv *rt712)
 int rt712_sdca_io_init(struct device *dev, struct sdw_slave *slave)
 {
 	struct rt712_sdca_priv *rt712 = dev_get_drvdata(dev);
-	int ret = 0;
 	unsigned int val;
 	struct sdw_slave_prop *prop = &slave->prop;
 
@@ -1829,15 +1840,22 @@ int rt712_sdca_io_init(struct device *dev, struct sdw_slave *slave)
 	rt712->version_id = (val & 0x0f00) >> 8;
 	dev_dbg(&slave->dev, "%s hw_id=0x%x, version_id=0x%x\n", __func__, rt712->hw_id, rt712->version_id);
 
-	if (rt712->version_id == RT712_VA)
+	if (rt712->version_id == RT712_VA) {
+		if (rt712->dmic_function_found) {
+			dev_err(&slave->dev, "%s RT712 VA detected but SMART_MIC function exposed in ACPI\n",
+				__func__);
+			goto suspend;
+		}
+
 		rt712_sdca_va_io_init(rt712);
-	else {
+	} else {
+		if (!rt712->dmic_function_found) {
+			dev_err(&slave->dev, "%s RT712 VB detected but no SMART_MIC function exposed in ACPI\n",
+				__func__);
+			goto suspend;
+		}
+
 		/* multilanes and DMIC are supported by rt712vb */
-		ret =  devm_snd_soc_register_component(dev,
-			&soc_sdca_dev_rt712_dmic, rt712_sdca_dmic_dai, ARRAY_SIZE(rt712_sdca_dmic_dai));
-		if (ret < 0)
-			return ret;
-
 		prop->lane_control_support = true;
 		rt712_sdca_vb_io_init(rt712);
 	}
@@ -1862,10 +1880,12 @@ int rt712_sdca_io_init(struct device *dev, struct sdw_slave *slave)
 	/* Mark Slave initialization complete */
 	rt712->hw_init = true;
 
+	dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
+
+suspend:
 	pm_runtime_mark_last_busy(&slave->dev);
 	pm_runtime_put_autosuspend(&slave->dev);
 
-	dev_dbg(&slave->dev, "%s hw_init complete\n", __func__);
 	return 0;
 }
 
diff --git a/sound/soc/codecs/rt712-sdca.h b/sound/soc/codecs/rt712-sdca.h
index 2169f2f726b9..a08491496d90 100644
--- a/sound/soc/codecs/rt712-sdca.h
+++ b/sound/soc/codecs/rt712-sdca.h
@@ -36,6 +36,7 @@ struct  rt712_sdca_priv {
 	unsigned int scp_sdca_stat2;
 	unsigned int hw_id;
 	unsigned int version_id;
+	bool dmic_function_found;
 	bool fu0f_dapm_mute;
 	bool fu0f_mixer_l_mute;
 	bool fu0f_mixer_r_mute;
-- 
2.43.0


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

* [PATCH 07/11] ASoC: soc-acpi: introduce new 'machine check' callback
  2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
                   ` (5 preceding siblings ...)
  2024-10-16 10:23 ` [PATCH 06/11] ASoC: rt712-sdca: detect the SMART_MIC function during the probe stage Bard Liao
@ 2024-10-16 10:23 ` Bard Liao
  2024-10-16 10:23 ` [PATCH 08/11] ASoC: sdw_utils: add SmartMic DAI for RT712 VB Bard Liao
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Bard Liao @ 2024-10-16 10:23 UTC (permalink / raw)
  To: broonie, tiwai, vkoul
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

The existing machine_quirk() returns a pointer to a soc_acpi_mach
structure.
For SoundWire/SDCA support, we need a slightly different
functionality where a quirk function either validates or NACKs an
initial selection, based on additional firmware/DMI information.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 include/sound/soc-acpi.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h
index ac7f9e791ee1..72e371a21767 100644
--- a/include/sound/soc-acpi.h
+++ b/include/sound/soc-acpi.h
@@ -185,6 +185,10 @@ struct snd_soc_acpi_link_adr {
  * ACPI ID alone is not sufficient, wrong or misleading
  * @quirk_data: data used to uniquely identify a machine, usually a list of
  * audio codecs whose presence if checked with ACPI
+ * @machine_check: pointer to quirk function. The functionality is similar to
+ * the use of @machine_quirk, except that the return value is a boolean: the intent
+ * is to skip a machine if the additional hardware/firmware verification invalidates
+ * the initial selection in the snd_soc_acpi_mach table.
  * @pdata: intended for platform data or machine specific-ops. This structure
  *  is not constant since this field may be updated at run-time
  * @sof_tplg_filename: Sound Open Firmware topology file name, if enabled
@@ -203,6 +207,7 @@ struct snd_soc_acpi_mach {
 	const char *board;
 	struct snd_soc_acpi_mach * (*machine_quirk)(void *arg);
 	const void *quirk_data;
+	bool (*machine_check)(void *arg);
 	void *pdata;
 	struct snd_soc_acpi_mach_params mach_params;
 	const char *sof_tplg_filename;
-- 
2.43.0


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

* [PATCH 08/11] ASoC: sdw_utils: add SmartMic DAI for RT712 VB
  2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
                   ` (6 preceding siblings ...)
  2024-10-16 10:23 ` [PATCH 07/11] ASoC: soc-acpi: introduce new 'machine check' callback Bard Liao
@ 2024-10-16 10:23 ` Bard Liao
  2024-10-16 10:23 ` [PATCH 09/11] ASoC: sdw_utils: add SmartMic DAI for RT713 VB Bard Liao
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Bard Liao @ 2024-10-16 10:23 UTC (permalink / raw)
  To: broonie, tiwai, vkoul
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

In theory the dailinks are created based on the number of endpoints
reported in ACPI match tables, so it should harmless to add a new
dailink: RT712 VA would not use it since it has only 2 endpoints.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 sound/soc/sdw_utils/soc_sdw_utils.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index 6f6bff0f69fc..9fc07731a05b 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -144,8 +144,15 @@ struct asoc_sdw_codec_info codec_info_list[] = {
 				.widgets = generic_spk_widgets,
 				.num_widgets = ARRAY_SIZE(generic_spk_widgets),
 			},
+			{
+				.direction = {false, true},
+				.dai_name = "rt712-sdca-aif3",
+				.dai_type = SOC_SDW_DAI_TYPE_MIC,
+				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
+			},
 		},
-		.dai_num = 2,
+		.dai_num = 3,
 	},
 	{
 		.part_id = 0x1712,
-- 
2.43.0


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

* [PATCH 09/11] ASoC: sdw_utils: add SmartMic DAI for RT713 VB
  2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
                   ` (7 preceding siblings ...)
  2024-10-16 10:23 ` [PATCH 08/11] ASoC: sdw_utils: add SmartMic DAI for RT712 VB Bard Liao
@ 2024-10-16 10:23 ` Bard Liao
  2024-10-16 10:23 ` [PATCH 10/11] ASoC: Intel: soc-acpi: add is_device_rt712_vb() helper Bard Liao
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Bard Liao @ 2024-10-16 10:23 UTC (permalink / raw)
  To: broonie, tiwai, vkoul
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

In theory the dailinks are created based on the number of endpoints
reported in ACPI match tables, so it should harmless to add a new
dailink: RT713 VA would not use it since it has only 2 endpoints.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 sound/soc/sdw_utils/soc_sdw_utils.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index 9fc07731a05b..8196177ff5e7 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -185,8 +185,15 @@ struct asoc_sdw_codec_info codec_info_list[] = {
 				.widgets = generic_jack_widgets,
 				.num_widgets = ARRAY_SIZE(generic_jack_widgets),
 			},
+			{
+				.direction = {false, true},
+				.dai_name = "rt712-sdca-aif3",
+				.dai_type = SOC_SDW_DAI_TYPE_MIC,
+				.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+				.rtd_init = asoc_sdw_rt_dmic_rtd_init,
+			},
 		},
-		.dai_num = 1,
+		.dai_num = 2,
 	},
 	{
 		.part_id = 0x1713,
-- 
2.43.0


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

* [PATCH 10/11] ASoC: Intel: soc-acpi: add is_device_rt712_vb() helper
  2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
                   ` (8 preceding siblings ...)
  2024-10-16 10:23 ` [PATCH 09/11] ASoC: sdw_utils: add SmartMic DAI for RT713 VB Bard Liao
@ 2024-10-16 10:23 ` Bard Liao
  2024-10-16 10:23 ` [PATCH 11/11] ASoC: SOF: Intel: hda: use machine_check() for SoundWire Bard Liao
  2024-10-18 21:30 ` [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Mark Brown
  11 siblings, 0 replies; 15+ messages in thread
From: Bard Liao @ 2024-10-16 10:23 UTC (permalink / raw)
  To: broonie, tiwai, vkoul
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

Add a filter to skip the RT172 VB configuration if a SmartMic Function
is not found in the SDCA descriptors.

If the ACPI information is incorrect this can only be quirked further
with DMI information.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 sound/soc/intel/Kconfig                       |  5 ++
 sound/soc/intel/common/Makefile               |  3 ++
 .../intel/common/soc-acpi-intel-mtl-match.c   | 51 +++++++++++++++++++
 .../intel/common/soc-acpi-intel-sdca-quirks.c | 42 +++++++++++++++
 .../intel/common/soc-acpi-intel-sdca-quirks.h | 14 +++++
 5 files changed, 115 insertions(+)
 create mode 100644 sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
 create mode 100644 sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h

diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index 5bb7047c170f..14461dee3e52 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -71,9 +71,14 @@ if SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL
 config SND_SOC_ACPI_INTEL_MATCH
 	tristate
 	select SND_SOC_ACPI if ACPI
+	select SND_SOC_ACPI_INTEL_SDCA_QUIRKS
 	# this option controls the compilation of ACPI matching tables and
 	# helpers and is not meant to be selected by the user.
 
+config SND_SOC_ACPI_INTEL_SDCA_QUIRKS
+	tristate
+	imply SND_SOC_SDCA
+
 endif ## SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL
 
 config SND_SOC_INTEL_KEEMBAY
diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile
index da551144ec0f..0afd114be9e5 100644
--- a/sound/soc/intel/common/Makefile
+++ b/sound/soc/intel/common/Makefile
@@ -16,4 +16,7 @@ snd-soc-acpi-intel-match-y := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-matc
 
 snd-soc-acpi-intel-match-y += soc-acpi-intel-ssp-common.o
 
+snd-soc-acpi-intel-sdca-quirks-y += soc-acpi-intel-sdca-quirks.o
+
 obj-$(CONFIG_SND_SOC_ACPI_INTEL_MATCH) += snd-soc-acpi-intel-match.o
+obj-$(CONFIG_SND_SOC_ACPI_INTEL_SDCA_QUIRKS) += snd-soc-acpi-intel-sdca-quirks.o
diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
index fd02c864e25e..0b37465b6c53 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -6,9 +6,12 @@
  *
  */
 
+#include <linux/soundwire/sdw_intel.h>
+#include <sound/sdca.h>
 #include <sound/soc-acpi.h>
 #include <sound/soc-acpi-intel-match.h>
 #include <sound/soc-acpi-intel-ssp-common.h>
+#include "soc-acpi-intel-sdca-quirks.h"
 #include "soc-acpi-intel-sdw-mockup-match.h"
 
 static const struct snd_soc_acpi_codecs mtl_rt5682_rt5682s_hp = {
@@ -133,6 +136,27 @@ static const struct snd_soc_acpi_endpoint rt712_endpoints[] = {
 	},
 };
 
+static const struct snd_soc_acpi_endpoint rt712_vb_endpoints[] = {
+	{
+		.num = 0,
+		.aggregated = 0,
+		.group_position = 0,
+		.group_id = 0,
+	},
+	{
+		.num = 1,
+		.aggregated = 0,
+		.group_position = 0,
+		.group_id = 0,
+	},
+	{
+		.num = 2,
+		.aggregated = 0,
+		.group_position = 0,
+		.group_id = 0,
+	},
+};
+
 /*
  * RT722 is a multi-function codec, three endpoints are created for
  * its headset, amp and dmic functions.
@@ -190,6 +214,15 @@ static const struct snd_soc_acpi_adr_device rt712_0_single_adr[] = {
 	}
 };
 
+static const struct snd_soc_acpi_adr_device rt712_vb_0_single_adr[] = {
+	{
+		.adr = 0x000030025D071201ull,
+		.num_endpoints = ARRAY_SIZE(rt712_vb_endpoints),
+		.endpoints = rt712_vb_endpoints,
+		.name_prefix = "rt712"
+	}
+};
+
 static const struct snd_soc_acpi_adr_device rt1712_3_single_adr[] = {
 	{
 		.adr = 0x000330025D171201ull,
@@ -363,6 +396,15 @@ static const struct snd_soc_acpi_link_adr mtl_712_l0[] = {
 	{}
 };
 
+static const struct snd_soc_acpi_link_adr mtl_712_vb_l0[] = {
+	{
+		.mask = BIT(0),
+		.num_adr = ARRAY_SIZE(rt712_vb_0_single_adr),
+		.adr_d = rt712_vb_0_single_adr,
+	},
+	{}
+};
+
 static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = {
 	{ /* Jack Playback Endpoint */
 		.num = 0,
@@ -774,6 +816,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
 		.drv_name = "sof_sdw",
 		.sof_tplg_filename = "sof-mtl-rt712-l0-rt1712-l3.tplg",
 	},
+	{
+		.link_mask = BIT(0),
+		.links = mtl_712_vb_l0,
+		.drv_name = "sof_sdw",
+		.machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb,
+		.sof_tplg_filename = "sof-mtl-rt712-vb-l0.tplg",
+	},
 	{
 		.link_mask = BIT(0),
 		.links = mtl_712_l0,
@@ -843,3 +892,5 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
 	{},
 };
 EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_sdw_machines);
+
+MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_SDCA_QUIRKS);
diff --git a/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
new file mode 100644
index 000000000000..0b7076606d66
--- /dev/null
+++ b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * soc-acpi-intel-sdca-quirks.c - tables and support for SDCA quirks
+ *
+ * Copyright (c) 2024, Intel Corporation.
+ *
+ */
+
+#include <linux/soundwire/sdw_intel.h>
+#include <sound/sdca.h>
+#include <sound/soc-acpi.h>
+#include "soc-acpi-intel-sdca-quirks.h"
+
+/*
+ * Pretend machine quirk. The argument type is not the traditional
+ * 'struct snd_soc_acpi_mach' pointer but instead the sdw_intel_ctx
+ * which contains the peripheral information required for the
+ * SoundWire/SDCA filter on the SMART_MIC setup and interface
+ * revision. When the return value is false, the entry in the
+ * 'snd_soc_acpi_mach' table needs to be skipped.
+ */
+bool snd_soc_acpi_intel_sdca_is_device_rt712_vb(void *arg)
+{
+	struct sdw_intel_ctx *ctx = arg;
+	int i;
+
+	if (!ctx)
+		return false;
+
+	for (i = 0; i < ctx->peripherals->num_peripherals; i++) {
+		if (sdca_device_quirk_match(ctx->peripherals->array[i],
+					    SDCA_QUIRKS_RT712_VB))
+			return true;
+	}
+
+	return false;
+}
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_sdca_is_device_rt712_vb, SND_SOC_ACPI_INTEL_SDCA_QUIRKS);
+
+MODULE_DESCRIPTION("ASoC ACPI Intel SDCA quirks");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SND_SOC_SDCA);
diff --git a/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h
new file mode 100644
index 000000000000..bead5ec6243f
--- /dev/null
+++ b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * soc-acpi-intel-sdca-quirks.h - tables and support for SDCA quirks
+ *
+ * Copyright (c) 2024, Intel Corporation.
+ *
+ */
+
+#ifndef _SND_SOC_ACPI_INTEL_SDCA_QUIRKS
+#define _SND_SOC_ACPI_INTEL_SDCA_QUIRKS
+
+bool snd_soc_acpi_intel_sdca_is_device_rt712_vb(void *arg);
+
+#endif
-- 
2.43.0


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

* [PATCH 11/11] ASoC: SOF: Intel: hda: use machine_check() for SoundWire
  2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
                   ` (9 preceding siblings ...)
  2024-10-16 10:23 ` [PATCH 10/11] ASoC: Intel: soc-acpi: add is_device_rt712_vb() helper Bard Liao
@ 2024-10-16 10:23 ` Bard Liao
  2024-10-18 21:30 ` [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Mark Brown
  11 siblings, 0 replies; 15+ messages in thread
From: Bard Liao @ 2024-10-16 10:23 UTC (permalink / raw)
  To: broonie, tiwai, vkoul
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>

Use the new machine_check() callback to select an alternate topology
for RT712-VB devices.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
---
 sound/soc/sof/intel/hda.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 9abc4c071ae5..38921c0db84e 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -1124,7 +1124,8 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
 		}
 		/* Found if all Slaves are checked */
 		if (i == hdev->info.count || !link->num_adr)
-			break;
+			if (!mach->machine_check || mach->machine_check(hdev->sdw))
+				break;
 	}
 	if (mach && mach->link_mask) {
 		mach->mach_params.links = mach->links;
-- 
2.43.0


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

* Re: [PATCH 01/11] soundwire: sdw_intel: include linux/acpi.h
  2024-10-16 10:23 ` [PATCH 01/11] soundwire: sdw_intel: include linux/acpi.h Bard Liao
@ 2024-10-17 12:23   ` Vinod Koul
  0 siblings, 0 replies; 15+ messages in thread
From: Vinod Koul @ 2024-10-17 12:23 UTC (permalink / raw)
  To: Bard Liao
  Cc: broonie, tiwai, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

On 16-10-24, 18:23, Bard Liao wrote:
> For the acpi_handle stuff.

Acked-by: Vinod Koul <vkoul@kernel.org>


-- 
~Vinod

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

* Re: [PATCH 04/11] soundwire: slave: lookup SDCA version and functions
  2024-10-16 10:23 ` [PATCH 04/11] soundwire: slave: lookup SDCA version and functions Bard Liao
@ 2024-10-17 12:24   ` Vinod Koul
  0 siblings, 0 replies; 15+ messages in thread
From: Vinod Koul @ 2024-10-17 12:24 UTC (permalink / raw)
  To: Bard Liao
  Cc: broonie, tiwai, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

On 16-10-24, 18:23, Bard Liao wrote:
> From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> 
> Use SDCA helpers to get the basic information and store it in the
> slave context. The information will be optionally be used in codec
> drivers to register sub-devices for each Function.
> 
> When platforms are not based on ACPI the helpers do absolutely
> nothing.

Acked-by: Vinod Koul <vkoul@kernel.org>


-- 
~Vinod

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

* Re: [PATCH 00/11] ASoC/soundwire: add initial support for SDCA
  2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
                   ` (10 preceding siblings ...)
  2024-10-16 10:23 ` [PATCH 11/11] ASoC: SOF: Intel: hda: use machine_check() for SoundWire Bard Liao
@ 2024-10-18 21:30 ` Mark Brown
  11 siblings, 0 replies; 15+ messages in thread
From: Mark Brown @ 2024-10-18 21:30 UTC (permalink / raw)
  To: tiwai, vkoul, Bard Liao
  Cc: vinod.koul, linux-kernel, linux-sound, pierre-louis.bossart,
	bard.liao

On Wed, 16 Oct 2024 18:23:22 +0800, Bard Liao wrote:
> We need to get rt712 version by reading SDCA version and functions.
> This patch series adds initial support for SDCA and add a helper to tell
> if the codec is RT712_VB.
> 
> This series may go via the ASoC tree with Vinod's Acked-by tag.
> 
> Bard Liao (1):
>   soundwire: sdw_intel: include linux/acpi.h
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[01/11] soundwire: sdw_intel: include linux/acpi.h
        commit: f35533a0e60946ee3fb8adccf8a36024c6f1fe40
[02/11] ASoC/soundwire: remove sdw_slave_extended_id
        commit: 4b224ff80d6609811ec6ab5406a16c92825cfb1a
[03/11] ASoC: SDCA: add initial module
        commit: 3a513da1ae33972e59efeef7908061f1f24af480
[04/11] soundwire: slave: lookup SDCA version and functions
        commit: 0c673d2862534955241f339d7331f384b5ea44af
[05/11] ASoC: SDCA: add quirk function for RT712_VB match
        commit: fdb220399177177917dce52063b326a191a35a02
[06/11] ASoC: rt712-sdca: detect the SMART_MIC function during the probe stage
        commit: 9aa6df9cb82e8fd44132c481afc76eb7a7dbc398
[07/11] ASoC: soc-acpi: introduce new 'machine check' callback
        commit: dcf4694f200a67784e053eb5d1d70a191761ff4f
[08/11] ASoC: sdw_utils: add SmartMic DAI for RT712 VB
        commit: 9489db97f6f0d78c26eef8e7fc9c1371cef97b82
[09/11] ASoC: sdw_utils: add SmartMic DAI for RT713 VB
        commit: 7d6f2d5254b1786c8b3bd64c6295b14e1607965d
[10/11] ASoC: Intel: soc-acpi: add is_device_rt712_vb() helper
        commit: 5703ab86ff7bf079aa1ddf7a65b9727d0249383a
[11/11] ASoC: SOF: Intel: hda: use machine_check() for SoundWire
        commit: e92edcf8023d425c7abcf1d7abb5dcac53d106f5

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark


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

end of thread, other threads:[~2024-10-18 21:30 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-16 10:23 [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Bard Liao
2024-10-16 10:23 ` [PATCH 01/11] soundwire: sdw_intel: include linux/acpi.h Bard Liao
2024-10-17 12:23   ` Vinod Koul
2024-10-16 10:23 ` [PATCH 02/11] ASoC/soundwire: remove sdw_slave_extended_id Bard Liao
2024-10-16 10:23 ` [PATCH 03/11] ASoC: SDCA: add initial module Bard Liao
2024-10-16 10:23 ` [PATCH 04/11] soundwire: slave: lookup SDCA version and functions Bard Liao
2024-10-17 12:24   ` Vinod Koul
2024-10-16 10:23 ` [PATCH 05/11] ASoC: SDCA: add quirk function for RT712_VB match Bard Liao
2024-10-16 10:23 ` [PATCH 06/11] ASoC: rt712-sdca: detect the SMART_MIC function during the probe stage Bard Liao
2024-10-16 10:23 ` [PATCH 07/11] ASoC: soc-acpi: introduce new 'machine check' callback Bard Liao
2024-10-16 10:23 ` [PATCH 08/11] ASoC: sdw_utils: add SmartMic DAI for RT712 VB Bard Liao
2024-10-16 10:23 ` [PATCH 09/11] ASoC: sdw_utils: add SmartMic DAI for RT713 VB Bard Liao
2024-10-16 10:23 ` [PATCH 10/11] ASoC: Intel: soc-acpi: add is_device_rt712_vb() helper Bard Liao
2024-10-16 10:23 ` [PATCH 11/11] ASoC: SOF: Intel: hda: use machine_check() for SoundWire Bard Liao
2024-10-18 21:30 ` [PATCH 00/11] ASoC/soundwire: add initial support for SDCA Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox