mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 17:25:38 +00:00
ASoC: amd: ps: refactor acp device configuration read logic
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>
This commit is contained in:
parent
cf88ab486a
commit
0386d765f2
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 (!addr)
|
||||
return -ENODEV;
|
||||
|
||||
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;
|
||||
}
|
||||
sdw_dev = acpi_find_child_device(ACPI_COMPANION(dev), addr, 0);
|
||||
if (!sdw_dev)
|
||||
return -ENODEV;
|
||||
|
||||
if (!count) {
|
||||
dev_dbg(dev, "No SoundWire Managers detected\n");
|
||||
return -EINVAL;
|
||||
acp_data->info.handle = sdw_dev->handle;
|
||||
acp_data->info.count = AMD_SDW_MAX_MANAGERS;
|
||||
return amd_sdw_scan_controller(&acp_data->info);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_acp63_device_config(u32 config, struct pci_dev *pci, struct acp63_dev_data *acp_data)
|
||||
#else
|
||||
static int acp_scan_sdw_devices(struct device *dev, u64 addr)
|
||||
{
|
||||
struct acpi_device *dmic_dev;
|
||||
struct acpi_device *sdw_dev;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int get_acp63_device_config(struct pci_dev *pci, struct acp63_dev_data *acp_data)
|
||||
{
|
||||
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");
|
||||
|
Loading…
Reference in New Issue
Block a user