diff mbox series

[1/5] ASoC: amd: ps: refactor acp device configuration read logic

Message ID 20240214104014.1144668-1-Vijendar.Mukunda@amd.com
State Accepted
Commit 0386d765f27a1fd3ed2ed6388a07e26d9659936d
Headers show
Series [1/5] ASoC: amd: ps: refactor acp device configuration read logic | expand

Commit Message

Mukunda,Vijendar Feb. 14, 2024, 10:40 a.m. UTC
Refactor acp device configuration read logic and use common function
to scan SoundWire devices.

Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
---
 sound/soc/amd/Kconfig     |  17 ++++
 sound/soc/amd/ps/acp63.h  |  11 +++
 sound/soc/amd/ps/pci-ps.c | 176 +++++++++++---------------------------
 3 files changed, 78 insertions(+), 126 deletions(-)
diff mbox series

Patch

diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 273688c05317..fa74635cee08 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -132,9 +132,26 @@  config SND_SOC_AMD_RPL_ACP6x
           Say m if you have such a device.
           If unsure select "N".
 
+config SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE
+	tristate
+	select SOUNDWIRE_AMD if SND_SOC_AMD_SOUNDWIRE != n
+	select SND_AMD_SOUNDWIRE_ACPI if ACPI
+
+config SND_SOC_AMD_SOUNDWIRE
+	tristate "Support for SoundWire based AMD platforms"
+	default SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE
+	depends on SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE
+	depends on ACPI && SOUNDWIRE
+	depends on !(SOUNDWIRE=m && SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE=y)
+	help
+	  This adds support for SoundWire for AMD platforms.
+	  Say Y if you want to enable SoundWire links with SOF.
+	  If unsure select "N".
+
 config SND_SOC_AMD_PS
         tristate "AMD Audio Coprocessor-v6.3 Pink Sardine support"
 	select SND_AMD_ACP_CONFIG
+	select SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE
         depends on X86 && PCI && ACPI
         help
           This option enables Audio Coprocessor i.e ACP v6.3 support on
diff --git a/sound/soc/amd/ps/acp63.h b/sound/soc/amd/ps/acp63.h
index 8b853b8d0219..123b9ade69d4 100644
--- a/sound/soc/amd/ps/acp63.h
+++ b/sound/soc/amd/ps/acp63.h
@@ -5,6 +5,7 @@ 
  * Copyright (C) 2022, 2023 Advanced Micro Devices, Inc. All rights reserved.
  */
 
+#include <linux/soundwire/sdw_amd.h>
 #include <sound/acp63_chip_offset_byte.h>
 
 #define ACP_DEVICE_ID 0x15E2
@@ -263,6 +264,11 @@  struct sdw_dma_ring_buf_reg {
  * @sdw0_dev_index: SoundWire Manager-0 platform device index
  * @sdw1_dev_index: SoundWire Manager-1 platform device index
  * @sdw_dma_dev_index: SoundWire DMA controller platform device index
+ * @info: SoundWire AMD information found in ACPI tables
+ * @is_sdw_dev: flag set to true when any SoundWire manager instances are available
+ * @is_pdm_dev: flag set to true when ACP PDM controller exists
+ * @is_pdm_config: flat set to true when PDM configuration is selected from BIOS
+ * @is_sdw_config: flag set to true when SDW configuration is selected from BIOS
  * @sdw0-dma_intr_stat: DMA interrupt status array for SoundWire manager-SW0 instance
  * @sdw_dma_intr_stat: DMA interrupt status array for SoundWire manager-SW1 instance
  * @acp_reset: flag set to true when bus reset is applied across all
@@ -282,6 +288,11 @@  struct acp63_dev_data {
 	u16 sdw0_dev_index;
 	u16 sdw1_dev_index;
 	u16 sdw_dma_dev_index;
+	struct sdw_amd_acpi_info info;
+	bool is_sdw_dev;
+	bool is_pdm_dev;
+	bool is_pdm_config;
+	bool is_sdw_config;
 	u16 sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS];
 	u16 sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS];
 	bool acp_reset;
diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c
index 5927eef04170..c97e418a88ce 100644
--- a/sound/soc/amd/ps/pci-ps.c
+++ b/sound/soc/amd/ps/pci-ps.c
@@ -237,122 +237,51 @@  static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
 		return IRQ_NONE;
 }
 
-static int sdw_amd_scan_controller(struct device *dev)
+#if IS_ENABLED(CONFIG_SND_SOC_AMD_SOUNDWIRE)
+static int acp_scan_sdw_devices(struct device *dev, u64 addr)
 {
+	struct acpi_device *sdw_dev;
 	struct acp63_dev_data *acp_data;
-	struct fwnode_handle *link;
-	char name[32];
-	u32 sdw_manager_bitmap;
-	u8 count = 0;
-	u32 acp_sdw_power_mode = 0;
-	int index;
-	int ret;
 
 	acp_data = dev_get_drvdata(dev);
-	/*
-	 * Current implementation is based on MIPI DisCo 2.0 spec.
-	 * Found controller, find links supported.
-	 */
-	ret = fwnode_property_read_u32_array((acp_data->sdw_fw_node), "mipi-sdw-manager-list",
-					     &sdw_manager_bitmap, 1);
-
-	if (ret) {
-		dev_dbg(dev, "Failed to read mipi-sdw-manager-list: %d\n", ret);
-		return -EINVAL;
-	}
-	count = hweight32(sdw_manager_bitmap);
-	/* Check count is within bounds */
-	if (count > AMD_SDW_MAX_MANAGERS) {
-		dev_err(dev, "Manager count %d exceeds max %d\n", count, AMD_SDW_MAX_MANAGERS);
-		return -EINVAL;
-	}
+	if (!addr)
+		return -ENODEV;
 
-	if (!count) {
-		dev_dbg(dev, "No SoundWire Managers detected\n");
-		return -EINVAL;
-	}
-	dev_dbg(dev, "ACPI reports %d SoundWire Manager devices\n", count);
-	acp_data->sdw_manager_count = count;
-	for (index = 0; index < count; index++) {
-		scnprintf(name, sizeof(name), "mipi-sdw-link-%d-subproperties", index);
-		link = fwnode_get_named_child_node(acp_data->sdw_fw_node, name);
-		if (!link) {
-			dev_err(dev, "Manager node %s not found\n", name);
-			return -EIO;
-		}
+	sdw_dev = acpi_find_child_device(ACPI_COMPANION(dev), addr, 0);
+	if (!sdw_dev)
+		return -ENODEV;
 
-		ret = fwnode_property_read_u32(link, "amd-sdw-power-mode", &acp_sdw_power_mode);
-		if (ret)
-			return ret;
-		/*
-		 * when SoundWire configuration is selected from acp pin config,
-		 * based on manager instances count, acp init/de-init sequence should be
-		 * executed as part of PM ops only when Bus reset is applied for the active
-		 * SoundWire manager instances.
-		 */
-		if (acp_sdw_power_mode != AMD_SDW_POWER_OFF_MODE) {
-			acp_data->acp_reset = false;
-			return 0;
-		}
-	}
+	acp_data->info.handle = sdw_dev->handle;
+	acp_data->info.count = AMD_SDW_MAX_MANAGERS;
+	return amd_sdw_scan_controller(&acp_data->info);
+}
+#else
+static int acp_scan_sdw_devices(struct device *dev, u64 addr)
+{
 	return 0;
 }
+#endif
 
-static int get_acp63_device_config(u32 config, struct pci_dev *pci, struct acp63_dev_data *acp_data)
+static int get_acp63_device_config(struct pci_dev *pci, struct acp63_dev_data *acp_data)
 {
-	struct acpi_device *dmic_dev;
-	struct acpi_device *sdw_dev;
+	struct acpi_device *pdm_dev;
 	const union acpi_object *obj;
+	u32 config;
 	bool is_dmic_dev = false;
 	bool is_sdw_dev = false;
 	int ret;
 
-	dmic_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_DMIC_ADDR, 0);
-	if (dmic_dev) {
-		/* is_dmic_dev flag will be set when ACP PDM controller device exists */
-		if (!acpi_dev_get_property(dmic_dev, "acp-audio-device-type",
-					   ACPI_TYPE_INTEGER, &obj) &&
-					   obj->integer.value == ACP_DMIC_DEV)
-			is_dmic_dev = true;
-	}
-
-	sdw_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_SDW_ADDR, 0);
-	if (sdw_dev) {
-		acp_data->sdw_fw_node = acpi_fwnode_handle(sdw_dev);
-		ret = sdw_amd_scan_controller(&pci->dev);
-		/* is_sdw_dev flag will be set when SoundWire Manager device exists */
-		if (!ret)
-			is_sdw_dev = true;
-	}
-	if (!is_dmic_dev && !is_sdw_dev)
-		return -ENODEV;
-	dev_dbg(&pci->dev, "Audio Mode %d\n", config);
+	config = readl(acp_data->acp63_base + ACP_PIN_CONFIG);
 	switch (config) {
 	case ACP_CONFIG_4:
 	case ACP_CONFIG_5:
 	case ACP_CONFIG_10:
 	case ACP_CONFIG_11:
-		if (is_dmic_dev) {
-			acp_data->pdev_config = ACP63_PDM_DEV_CONFIG;
-			acp_data->pdev_count = ACP63_PDM_MODE_DEVS;
-		}
+		acp_data->is_pdm_config = true;
 		break;
 	case ACP_CONFIG_2:
 	case ACP_CONFIG_3:
-		if (is_sdw_dev) {
-			switch (acp_data->sdw_manager_count) {
-			case 1:
-				acp_data->pdev_config = ACP63_SDW_DEV_CONFIG;
-				acp_data->pdev_count = ACP63_SDW0_MODE_DEVS;
-				break;
-			case 2:
-				acp_data->pdev_config = ACP63_SDW_DEV_CONFIG;
-				acp_data->pdev_count = ACP63_SDW0_SDW1_MODE_DEVS;
-				break;
-			default:
-				return -EINVAL;
-			}
-		}
+		acp_data->is_sdw_config = true;
 		break;
 	case ACP_CONFIG_6:
 	case ACP_CONFIG_7:
@@ -360,40 +289,36 @@  static int get_acp63_device_config(u32 config, struct pci_dev *pci, struct acp63
 	case ACP_CONFIG_8:
 	case ACP_CONFIG_13:
 	case ACP_CONFIG_14:
-		if (is_dmic_dev && is_sdw_dev) {
-			switch (acp_data->sdw_manager_count) {
-			case 1:
-				acp_data->pdev_config = ACP63_SDW_PDM_DEV_CONFIG;
-				acp_data->pdev_count = ACP63_SDW0_PDM_MODE_DEVS;
-				break;
-			case 2:
-				acp_data->pdev_config = ACP63_SDW_PDM_DEV_CONFIG;
-				acp_data->pdev_count = ACP63_SDW0_SDW1_PDM_MODE_DEVS;
-				break;
-			default:
-				return -EINVAL;
-			}
-		} else if (is_dmic_dev) {
-			acp_data->pdev_config = ACP63_PDM_DEV_CONFIG;
-			acp_data->pdev_count = ACP63_PDM_MODE_DEVS;
-		} else if (is_sdw_dev) {
-			switch (acp_data->sdw_manager_count) {
-			case 1:
-				acp_data->pdev_config = ACP63_SDW_DEV_CONFIG;
-				acp_data->pdev_count = ACP63_SDW0_MODE_DEVS;
-				break;
-			case 2:
-				acp_data->pdev_config = ACP63_SDW_DEV_CONFIG;
-				acp_data->pdev_count = ACP63_SDW0_SDW1_MODE_DEVS;
-				break;
-			default:
-				return -EINVAL;
-			}
-		}
+		acp_data->is_pdm_config = true;
+		acp_data->is_sdw_config = true;
 		break;
 	default:
 		break;
 	}
+
+	if (acp_data->is_pdm_config) {
+		pdm_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_DMIC_ADDR, 0);
+		if (pdm_dev) {
+			/* is_dmic_dev flag will be set when ACP PDM controller device exists */
+			if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type",
+						   ACPI_TYPE_INTEGER, &obj) &&
+						   obj->integer.value == ACP_DMIC_DEV)
+				is_dmic_dev = true;
+		}
+	}
+
+	if (acp_data->is_sdw_config) {
+		ret = acp_scan_sdw_devices(&pci->dev, ACP63_SDW_ADDR);
+		if (!ret && acp_data->info.link_mask)
+			is_sdw_dev = true;
+	}
+
+	acp_data->is_pdm_dev = is_dmic_dev;
+	acp_data->is_sdw_dev = is_sdw_dev;
+	if (!is_dmic_dev && !is_sdw_dev) {
+		dev_dbg(&pci->dev, "No PDM or SoundWire manager devices found\n");
+		return -ENODEV;
+	}
 	return 0;
 }
 
@@ -576,7 +501,6 @@  static int snd_acp63_probe(struct pci_dev *pci,
 	struct acp63_dev_data *adata;
 	u32 addr;
 	u32 irqflags, flag;
-	int val;
 	int ret;
 
 	irqflags = IRQF_SHARED;
@@ -637,8 +561,7 @@  static int snd_acp63_probe(struct pci_dev *pci,
 		dev_err(&pci->dev, "ACP PCI IRQ request failed\n");
 		goto de_init;
 	}
-	val = readl(adata->acp63_base + ACP_PIN_CONFIG);
-	ret = get_acp63_device_config(val, pci, adata);
+	ret = get_acp63_device_config(pci, adata);
 	/* ACP PCI driver probe should be continued even PDM or SoundWire Devices are not found */
 	if (ret) {
 		dev_dbg(&pci->dev, "get acp device config failed:%d\n", ret);
@@ -740,4 +663,5 @@  module_pci_driver(ps_acp63_driver);
 MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
 MODULE_AUTHOR("Syed.SabaKareem@amd.com");
 MODULE_DESCRIPTION("AMD ACP Pink Sardine PCI driver");
+MODULE_IMPORT_NS(SND_AMD_SOUNDWIRE_ACPI);
 MODULE_LICENSE("GPL v2");