mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +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
3 changed files with 78 additions and 126 deletions
|
@ -132,9 +132,26 @@ config SND_SOC_AMD_RPL_ACP6x
|
||||||
Say m if you have such a device.
|
Say m if you have such a device.
|
||||||
If unsure select "N".
|
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
|
config SND_SOC_AMD_PS
|
||||||
tristate "AMD Audio Coprocessor-v6.3 Pink Sardine support"
|
tristate "AMD Audio Coprocessor-v6.3 Pink Sardine support"
|
||||||
select SND_AMD_ACP_CONFIG
|
select SND_AMD_ACP_CONFIG
|
||||||
|
select SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE
|
||||||
depends on X86 && PCI && ACPI
|
depends on X86 && PCI && ACPI
|
||||||
help
|
help
|
||||||
This option enables Audio Coprocessor i.e ACP v6.3 support on
|
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.
|
* Copyright (C) 2022, 2023 Advanced Micro Devices, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/soundwire/sdw_amd.h>
|
||||||
#include <sound/acp63_chip_offset_byte.h>
|
#include <sound/acp63_chip_offset_byte.h>
|
||||||
|
|
||||||
#define ACP_DEVICE_ID 0x15E2
|
#define ACP_DEVICE_ID 0x15E2
|
||||||
|
@ -263,6 +264,11 @@ struct sdw_dma_ring_buf_reg {
|
||||||
* @sdw0_dev_index: SoundWire Manager-0 platform device index
|
* @sdw0_dev_index: SoundWire Manager-0 platform device index
|
||||||
* @sdw1_dev_index: SoundWire Manager-1 platform device index
|
* @sdw1_dev_index: SoundWire Manager-1 platform device index
|
||||||
* @sdw_dma_dev_index: SoundWire DMA controller 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
|
* @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
|
* @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
|
* @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 sdw0_dev_index;
|
||||||
u16 sdw1_dev_index;
|
u16 sdw1_dev_index;
|
||||||
u16 sdw_dma_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 sdw0_dma_intr_stat[ACP63_SDW0_DMA_MAX_STREAMS];
|
||||||
u16 sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS];
|
u16 sdw1_dma_intr_stat[ACP63_SDW1_DMA_MAX_STREAMS];
|
||||||
bool acp_reset;
|
bool acp_reset;
|
||||||
|
|
|
@ -237,122 +237,51 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
|
||||||
return IRQ_NONE;
|
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 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);
|
acp_data = dev_get_drvdata(dev);
|
||||||
/*
|
if (!addr)
|
||||||
* Current implementation is based on MIPI DisCo 2.0 spec.
|
return -ENODEV;
|
||||||
* 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) {
|
sdw_dev = acpi_find_child_device(ACPI_COMPANION(dev), addr, 0);
|
||||||
dev_dbg(dev, "Failed to read mipi-sdw-manager-list: %d\n", ret);
|
if (!sdw_dev)
|
||||||
return -EINVAL;
|
return -ENODEV;
|
||||||
}
|
|
||||||
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 (!count) {
|
acp_data->info.handle = sdw_dev->handle;
|
||||||
dev_dbg(dev, "No SoundWire Managers detected\n");
|
acp_data->info.count = AMD_SDW_MAX_MANAGERS;
|
||||||
return -EINVAL;
|
return amd_sdw_scan_controller(&acp_data->info);
|
||||||
}
|
}
|
||||||
dev_dbg(dev, "ACPI reports %d SoundWire Manager devices\n", count);
|
#else
|
||||||
acp_data->sdw_manager_count = count;
|
static int acp_scan_sdw_devices(struct device *dev, u64 addr)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
struct acpi_device *dmic_dev;
|
return 0;
|
||||||
struct acpi_device *sdw_dev;
|
}
|
||||||
|
#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;
|
const union acpi_object *obj;
|
||||||
|
u32 config;
|
||||||
bool is_dmic_dev = false;
|
bool is_dmic_dev = false;
|
||||||
bool is_sdw_dev = false;
|
bool is_sdw_dev = false;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dmic_dev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), ACP63_DMIC_ADDR, 0);
|
config = readl(acp_data->acp63_base + ACP_PIN_CONFIG);
|
||||||
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);
|
|
||||||
switch (config) {
|
switch (config) {
|
||||||
case ACP_CONFIG_4:
|
case ACP_CONFIG_4:
|
||||||
case ACP_CONFIG_5:
|
case ACP_CONFIG_5:
|
||||||
case ACP_CONFIG_10:
|
case ACP_CONFIG_10:
|
||||||
case ACP_CONFIG_11:
|
case ACP_CONFIG_11:
|
||||||
if (is_dmic_dev) {
|
acp_data->is_pdm_config = true;
|
||||||
acp_data->pdev_config = ACP63_PDM_DEV_CONFIG;
|
|
||||||
acp_data->pdev_count = ACP63_PDM_MODE_DEVS;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ACP_CONFIG_2:
|
case ACP_CONFIG_2:
|
||||||
case ACP_CONFIG_3:
|
case ACP_CONFIG_3:
|
||||||
if (is_sdw_dev) {
|
acp_data->is_sdw_config = true;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ACP_CONFIG_6:
|
case ACP_CONFIG_6:
|
||||||
case ACP_CONFIG_7:
|
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_8:
|
||||||
case ACP_CONFIG_13:
|
case ACP_CONFIG_13:
|
||||||
case ACP_CONFIG_14:
|
case ACP_CONFIG_14:
|
||||||
if (is_dmic_dev && is_sdw_dev) {
|
acp_data->is_pdm_config = true;
|
||||||
switch (acp_data->sdw_manager_count) {
|
acp_data->is_sdw_config = true;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,7 +501,6 @@ static int snd_acp63_probe(struct pci_dev *pci,
|
||||||
struct acp63_dev_data *adata;
|
struct acp63_dev_data *adata;
|
||||||
u32 addr;
|
u32 addr;
|
||||||
u32 irqflags, flag;
|
u32 irqflags, flag;
|
||||||
int val;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
irqflags = IRQF_SHARED;
|
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");
|
dev_err(&pci->dev, "ACP PCI IRQ request failed\n");
|
||||||
goto de_init;
|
goto de_init;
|
||||||
}
|
}
|
||||||
val = readl(adata->acp63_base + ACP_PIN_CONFIG);
|
ret = get_acp63_device_config(pci, adata);
|
||||||
ret = get_acp63_device_config(val, pci, adata);
|
|
||||||
/* ACP PCI driver probe should be continued even PDM or SoundWire Devices are not found */
|
/* ACP PCI driver probe should be continued even PDM or SoundWire Devices are not found */
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_dbg(&pci->dev, "get acp device config failed:%d\n", 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("Vijendar.Mukunda@amd.com");
|
||||||
MODULE_AUTHOR("Syed.SabaKareem@amd.com");
|
MODULE_AUTHOR("Syed.SabaKareem@amd.com");
|
||||||
MODULE_DESCRIPTION("AMD ACP Pink Sardine PCI driver");
|
MODULE_DESCRIPTION("AMD ACP Pink Sardine PCI driver");
|
||||||
|
MODULE_IMPORT_NS(SND_AMD_SOUNDWIRE_ACPI);
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
Loading…
Add table
Reference in a new issue