ASoC: amd: ps: refactor acp device configuration read logic
authorVijendar Mukunda <Vijendar.Mukunda@amd.com>
Wed, 14 Feb 2024 10:40:01 +0000 (16:10 +0530)
committerMark Brown <broonie@kernel.org>
Mon, 19 Feb 2024 17:02:11 +0000 (17:02 +0000)
Refactor acp device configuration read logic and use common function
to scan SoundWire devices.

Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
Link: https://msgid.link/r/20240214104014.1144668-1-Vijendar.Mukunda@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/amd/Kconfig
sound/soc/amd/ps/acp63.h
sound/soc/amd/ps/pci-ps.c

index 273688c053172f267ca63e82eea4c1d778e41c04..fa74635cee08ea5bfc43ad589a6f579e1ca164a4 100644 (file)
@@ -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
index 8b853b8d02199232fa1d3f979f35c675ae8765ae..123b9ade69d4752f83caed50fda293921c8dd17d 100644 (file)
@@ -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;
index 5927eef04170011d345729357950874eb8e5341f..c97e418a88ce47e4efd8e9babdde0d5d419e7487 100644 (file)
@@ -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");