mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 17:13:52 +02:00
ASoC: SOF: amd: add soundwire IO support for ACP7.0 &
Merge series from Vijendar Mukunda <Vijendar.Mukunda@amd.com>: This patch series contains - ACP sof stack improvements - Add support for ACP7.1 platform. - Soundwire IO support for ACP7.0 & ACP7.1 platforms Link: https://github.com/thesofproject/linux/pull/5392
This commit is contained in:
commit
fe65ce845c
|
|
@ -94,13 +94,14 @@ config SND_SOC_SOF_AMD_ACP63
|
|||
If unsure select "N".
|
||||
|
||||
config SND_SOC_SOF_AMD_ACP70
|
||||
tristate "SOF support for ACP7.0 platform"
|
||||
tristate "SOF support for ACP7.0/ACP7.1 platforms"
|
||||
depends on SND_SOC_SOF_PCI
|
||||
depends on AMD_NODE
|
||||
select SND_SOC_SOF_AMD_COMMON
|
||||
select SND_SOC_SOF_AMD_SOUNDWIRE_LINK_BASELINE
|
||||
help
|
||||
Select this option for SOF support on
|
||||
AMD ACP7.0 version based platforms.
|
||||
Say Y if you want to enable SOF on ACP7.0 based platform.
|
||||
AMD ACP7.0/ACP7.1 version based platforms.
|
||||
Say Y if you want to enable SOF on ACP7.0/ACP7.1 based platforms.
|
||||
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -130,4 +130,14 @@
|
|||
|
||||
#define ACP_SW0_EN 0x3000
|
||||
#define ACP_SW1_EN 0x3C00
|
||||
#define ACP70_PME_EN 0x1400
|
||||
#define ACP70_EXTERNAL_INTR_CNTL1 0x1A08
|
||||
#define ACP70_SW0_WAKE_EN 0x1458
|
||||
#define ACP70_SW1_WAKE_EN 0x1460
|
||||
#define ACP70_SDW_HOST_WAKE_MASK 0x0C00000
|
||||
#define ACP70_SDW0_HOST_WAKE_STAT BIT(24)
|
||||
#define ACP70_SDW1_HOST_WAKE_STAT BIT(25)
|
||||
#define ACP70_SDW0_PME_STAT BIT(26)
|
||||
#define ACP70_SDW1_PME_STAT BIT(27)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ static void init_dma_descriptor(struct acp_dev_data *adata)
|
|||
|
||||
switch (acp_data->pci_rev) {
|
||||
case ACP70_PCI_ID:
|
||||
case ACP71_PCI_ID:
|
||||
acp_dma_desc_base_addr = ACP70_DMA_DESC_BASE_ADDR;
|
||||
acp_dma_desc_max_num_dscr = ACP70_DMA_DESC_MAX_NUM_DSCR;
|
||||
break;
|
||||
|
|
@ -97,6 +98,7 @@ static int config_dma_channel(struct acp_dev_data *adata, unsigned int ch,
|
|||
|
||||
switch (acp_data->pci_rev) {
|
||||
case ACP70_PCI_ID:
|
||||
case ACP71_PCI_ID:
|
||||
acp_dma_cntl_0 = ACP70_DMA_CNTL_0;
|
||||
acp_dma_ch_rst_sts = ACP70_DMA_CH_RST_STS;
|
||||
acp_dma_dscr_err_sts_0 = ACP70_DMA_ERR_STS_0;
|
||||
|
|
@ -336,6 +338,7 @@ int acp_dma_status(struct acp_dev_data *adata, unsigned char ch)
|
|||
|
||||
switch (adata->pci_rev) {
|
||||
case ACP70_PCI_ID:
|
||||
case ACP71_PCI_ID:
|
||||
acp_dma_ch_sts = ACP70_DMA_CH_STS;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -383,6 +386,69 @@ static int acp_memory_init(struct snd_sof_dev *sdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void amd_sof_handle_acp70_sdw_wake_event(struct acp_dev_data *adata)
|
||||
{
|
||||
struct amd_sdw_manager *amd_manager;
|
||||
|
||||
if (adata->acp70_sdw0_wake_event) {
|
||||
amd_manager = dev_get_drvdata(&adata->sdw->pdev[0]->dev);
|
||||
if (amd_manager)
|
||||
pm_request_resume(amd_manager->dev);
|
||||
adata->acp70_sdw0_wake_event = 0;
|
||||
}
|
||||
|
||||
if (adata->acp70_sdw1_wake_event) {
|
||||
amd_manager = dev_get_drvdata(&adata->sdw->pdev[1]->dev);
|
||||
if (amd_manager)
|
||||
pm_request_resume(amd_manager->dev);
|
||||
adata->acp70_sdw1_wake_event = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int amd_sof_check_and_handle_acp70_sdw_wake_irq(struct snd_sof_dev *sdev)
|
||||
{
|
||||
const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
|
||||
struct acp_dev_data *adata = sdev->pdata->hw_pdata;
|
||||
u32 ext_intr_stat1;
|
||||
int irq_flag = 0;
|
||||
bool sdw_wake_irq = false;
|
||||
|
||||
ext_intr_stat1 = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->ext_intr_stat1);
|
||||
if (ext_intr_stat1 & ACP70_SDW0_HOST_WAKE_STAT) {
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1,
|
||||
ACP70_SDW0_HOST_WAKE_STAT);
|
||||
adata->acp70_sdw0_wake_event = true;
|
||||
sdw_wake_irq = true;
|
||||
}
|
||||
|
||||
if (ext_intr_stat1 & ACP70_SDW1_HOST_WAKE_STAT) {
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1,
|
||||
ACP70_SDW1_HOST_WAKE_STAT);
|
||||
adata->acp70_sdw1_wake_event = true;
|
||||
sdw_wake_irq = true;
|
||||
}
|
||||
|
||||
if (ext_intr_stat1 & ACP70_SDW0_PME_STAT) {
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP70_SW0_WAKE_EN, 0);
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1, ACP70_SDW0_PME_STAT);
|
||||
adata->acp70_sdw0_wake_event = true;
|
||||
sdw_wake_irq = true;
|
||||
}
|
||||
|
||||
if (ext_intr_stat1 & ACP70_SDW1_PME_STAT) {
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP70_SW1_WAKE_EN, 0);
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1, ACP70_SDW1_PME_STAT);
|
||||
adata->acp70_sdw1_wake_event = true;
|
||||
sdw_wake_irq = true;
|
||||
}
|
||||
|
||||
if (sdw_wake_irq) {
|
||||
amd_sof_handle_acp70_sdw_wake_event(adata);
|
||||
irq_flag = 1;
|
||||
}
|
||||
return irq_flag;
|
||||
}
|
||||
|
||||
static irqreturn_t acp_irq_thread(int irq, void *context)
|
||||
{
|
||||
struct snd_sof_dev *sdev = context;
|
||||
|
|
@ -415,7 +481,7 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id)
|
|||
struct acp_dev_data *adata = sdev->pdata->hw_pdata;
|
||||
unsigned int base = desc->dsp_intr_base;
|
||||
unsigned int val;
|
||||
int irq_flag = 0;
|
||||
int irq_flag = 0, wake_irq_flag = 0;
|
||||
|
||||
val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET);
|
||||
if (val & ACP_DSP_TO_HOST_IRQ) {
|
||||
|
|
@ -453,8 +519,14 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id)
|
|||
schedule_work(&amd_manager->amd_sdw_irq_thread);
|
||||
irq_flag = 1;
|
||||
}
|
||||
switch (adata->pci_rev) {
|
||||
case ACP70_PCI_ID:
|
||||
case ACP71_PCI_ID:
|
||||
wake_irq_flag = amd_sof_check_and_handle_acp70_sdw_wake_irq(sdev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (irq_flag)
|
||||
if (irq_flag || wake_irq_flag)
|
||||
return IRQ_HANDLED;
|
||||
else
|
||||
return IRQ_NONE;
|
||||
|
|
@ -486,6 +558,7 @@ static int acp_power_on(struct snd_sof_dev *sdev)
|
|||
acp_pgfsm_cntl_mask = ACP6X_PGFSM_CNTL_POWER_ON_MASK;
|
||||
break;
|
||||
case ACP70_PCI_ID:
|
||||
case ACP71_PCI_ID:
|
||||
acp_pgfsm_status_mask = ACP70_PGFSM_STATUS_MASK;
|
||||
acp_pgfsm_cntl_mask = ACP70_PGFSM_CNTL_POWER_ON_MASK;
|
||||
break;
|
||||
|
|
@ -507,7 +580,6 @@ static int acp_power_on(struct snd_sof_dev *sdev)
|
|||
|
||||
static int acp_reset(struct snd_sof_dev *sdev)
|
||||
{
|
||||
const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
|
|
@ -528,14 +600,6 @@ static int acp_reset(struct snd_sof_dev *sdev)
|
|||
if (ret < 0)
|
||||
dev_err(sdev->dev, "timeout in releasing reset\n");
|
||||
|
||||
if (desc->acp_clkmux_sel)
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_clkmux_sel, ACP_CLOCK_ACLK);
|
||||
|
||||
if (desc->ext_intr_enb)
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_enb, 0x01);
|
||||
|
||||
if (desc->ext_intr_cntl)
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_cntl, ACP_ERROR_IRQ_MASK);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -566,9 +630,13 @@ static int acp_dsp_reset(struct snd_sof_dev *sdev)
|
|||
|
||||
static int acp_init(struct snd_sof_dev *sdev)
|
||||
{
|
||||
const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
|
||||
struct acp_dev_data *acp_data;
|
||||
unsigned int sdw0_wake_en, sdw1_wake_en;
|
||||
int ret;
|
||||
|
||||
/* power on */
|
||||
acp_data = sdev->pdata->hw_pdata;
|
||||
ret = acp_power_on(sdev);
|
||||
if (ret) {
|
||||
dev_err(sdev->dev, "ACP power on failed\n");
|
||||
|
|
@ -577,7 +645,32 @@ static int acp_init(struct snd_sof_dev *sdev)
|
|||
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_CONTROL, 0x01);
|
||||
/* Reset */
|
||||
return acp_reset(sdev);
|
||||
ret = acp_reset(sdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (desc->acp_clkmux_sel)
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->acp_clkmux_sel, ACP_CLOCK_ACLK);
|
||||
|
||||
if (desc->ext_intr_enb)
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_enb, 0x01);
|
||||
|
||||
if (desc->ext_intr_cntl)
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_cntl, ACP_ERROR_IRQ_MASK);
|
||||
|
||||
switch (acp_data->pci_rev) {
|
||||
case ACP70_PCI_ID:
|
||||
case ACP71_PCI_ID:
|
||||
sdw0_wake_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP70_SW0_WAKE_EN);
|
||||
sdw1_wake_en = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP70_SW1_WAKE_EN);
|
||||
if (sdw0_wake_en || sdw1_wake_en)
|
||||
snd_sof_dsp_update_bits(sdev, ACP_DSP_BAR, ACP70_EXTERNAL_INTR_CNTL1,
|
||||
ACP70_SDW_HOST_WAKE_MASK, ACP70_SDW_HOST_WAKE_MASK);
|
||||
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP70_PME_EN, 1);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool check_acp_sdw_enable_status(struct snd_sof_dev *sdev)
|
||||
|
|
@ -616,8 +709,12 @@ int amd_sof_acp_suspend(struct snd_sof_dev *sdev, u32 target_state)
|
|||
dev_err(sdev->dev, "ACP Reset failed\n");
|
||||
return ret;
|
||||
}
|
||||
if (acp_data->pci_rev == ACP70_PCI_ID)
|
||||
switch (acp_data->pci_rev) {
|
||||
case ACP70_PCI_ID:
|
||||
case ACP71_PCI_ID:
|
||||
enable = true;
|
||||
break;
|
||||
}
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_CONTROL, enable);
|
||||
|
||||
return 0;
|
||||
|
|
@ -637,9 +734,15 @@ int amd_sof_acp_resume(struct snd_sof_dev *sdev)
|
|||
return ret;
|
||||
}
|
||||
return acp_memory_init(sdev);
|
||||
} else {
|
||||
return acp_dsp_reset(sdev);
|
||||
}
|
||||
switch (acp_data->pci_rev) {
|
||||
case ACP70_PCI_ID:
|
||||
case ACP71_PCI_ID:
|
||||
snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP70_PME_EN, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return acp_dsp_reset(sdev);
|
||||
}
|
||||
EXPORT_SYMBOL_NS(amd_sof_acp_resume, "SND_SOC_SOF_AMD_COMMON");
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@
|
|||
#define ACP_RMB_PCI_ID 0x6F
|
||||
#define ACP63_PCI_ID 0x63
|
||||
#define ACP70_PCI_ID 0x70
|
||||
#define ACP71_PCI_ID 0x71
|
||||
|
||||
#define HOST_BRIDGE_CZN 0x1630
|
||||
#define HOST_BRIDGE_VGH 0x1645
|
||||
|
|
@ -109,9 +110,11 @@
|
|||
#define ACP_SDW0_IRQ_MASK BIT(21)
|
||||
#define ACP_SDW1_IRQ_MASK BIT(2)
|
||||
#define SDW_ACPI_ADDR_ACP63 5
|
||||
#define SDW_ACPI_ADDR_ACP70 SDW_ACPI_ADDR_ACP63
|
||||
#define ACP_DEFAULT_SRAM_LENGTH 0x00080000
|
||||
#define ACP_SRAM_PAGE_COUNT 128
|
||||
#define ACP6X_SDW_MAX_MANAGER_COUNT 2
|
||||
#define ACP70_SDW_MAX_MANAGER_COUNT ACP6X_SDW_MAX_MANAGER_COUNT
|
||||
|
||||
enum clock_source {
|
||||
ACP_CLOCK_96M = 0,
|
||||
|
|
@ -260,6 +263,10 @@ struct acp_dev_data {
|
|||
bool is_dram_in_use;
|
||||
bool is_sram_in_use;
|
||||
bool sdw_en_stat;
|
||||
/* acp70_sdw0_wake_event flag set to true when wake irq asserted for SW0 instance */
|
||||
bool acp70_sdw0_wake_event;
|
||||
/* acp70_sdw1_wake_event flag set to true when wake irq asserted for SW1 instance */
|
||||
bool acp70_sdw1_wake_event;
|
||||
unsigned int pci_rev;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -33,12 +33,15 @@ static const struct sof_amd_acp_desc acp70_chip_info = {
|
|||
.ext_intr_cntl = ACP70_EXTERNAL_INTR_CNTL,
|
||||
.ext_intr_stat = ACP70_EXT_INTR_STAT,
|
||||
.ext_intr_stat1 = ACP70_EXT_INTR_STAT1,
|
||||
.acp_error_stat = ACP70_ERROR_STATUS,
|
||||
.dsp_intr_base = ACP70_DSP_SW_INTR_BASE,
|
||||
.acp_sw0_i2s_err_reason = ACP7X_SW0_I2S_ERROR_REASON,
|
||||
.sram_pte_offset = ACP70_SRAM_PTE_OFFSET,
|
||||
.hw_semaphore_offset = ACP70_AXI2DAGB_SEM_0,
|
||||
.fusion_dsp_offset = ACP70_DSP_FUSION_RUNSTALL,
|
||||
.probe_reg_offset = ACP70_FUTURE_REG_ACLK_0,
|
||||
.sdw_max_link_count = ACP70_SDW_MAX_MANAGER_COUNT,
|
||||
.sdw_acpi_dev_addr = SDW_ACPI_ADDR_ACP70,
|
||||
.reg_start_addr = ACP70_REG_START,
|
||||
.reg_end_addr = ACP70_REG_END,
|
||||
};
|
||||
|
|
@ -70,8 +73,13 @@ static int acp70_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_
|
|||
{
|
||||
unsigned int flag;
|
||||
|
||||
if (pci->revision != ACP70_PCI_ID)
|
||||
switch (pci->revision) {
|
||||
case ACP70_PCI_ID:
|
||||
case ACP71_PCI_ID:
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
flag = snd_amd_acp_find_config(pci);
|
||||
if (flag != FLAG_AMD_SOF && flag != FLAG_AMD_SOF_ONLY_DMIC)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user