summaryrefslogtreecommitdiff
path: root/sound/soc/amd/acp
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/amd/acp')
-rw-r--r--sound/soc/amd/acp/Kconfig12
-rw-r--r--sound/soc/amd/acp/Makefile4
-rw-r--r--sound/soc/amd/acp/acp-i2s.c187
-rw-r--r--sound/soc/amd/acp/acp-legacy-common.c308
-rw-r--r--sound/soc/amd/acp/acp-mach-common.c2
-rw-r--r--sound/soc/amd/acp/acp-pci.c220
-rw-r--r--sound/soc/amd/acp/acp-pdm.c53
-rw-r--r--sound/soc/amd/acp/acp-platform.c145
-rw-r--r--sound/soc/amd/acp/acp-rembrandt.c149
-rw-r--r--sound/soc/amd/acp/acp-renoir.c116
-rw-r--r--sound/soc/amd/acp/acp-sdw-legacy-mach.c49
-rw-r--r--sound/soc/amd/acp/acp-sdw-mach-common.c34
-rw-r--r--sound/soc/amd/acp/acp-sdw-sof-mach.c10
-rw-r--r--sound/soc/amd/acp/acp-sof-mach.c2
-rw-r--r--sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c5
-rw-r--r--sound/soc/amd/acp/acp63.c163
-rw-r--r--sound/soc/amd/acp/acp70.c132
-rw-r--r--sound/soc/amd/acp/amd-acp70-acpi-match.c160
-rw-r--r--sound/soc/amd/acp/amd-acpi-mach.c93
-rw-r--r--sound/soc/amd/acp/amd.h168
-rw-r--r--sound/soc/amd/acp/chip_offset_byte.h12
-rw-r--r--sound/soc/amd/acp/soc_amd_sdw_common.h12
22 files changed, 1185 insertions, 851 deletions
diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 03f3fcbba5af..b9432052c638 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -28,6 +28,9 @@ config SND_SOC_AMD_ACP_LEGACY_COMMON
config SND_SOC_AMD_ACP_I2S
tristate
+config SND_SOC_AMD_ACPI_MACH
+ tristate
+
config SND_SOC_AMD_ACP_PCM
tristate
select SND_SOC_ACPI if ACPI
@@ -37,6 +40,7 @@ config SND_SOC_AMD_ACP_PCI
depends on X86 && PCI
depends on ACPI
select SND_SOC_AMD_ACP_LEGACY_COMMON
+ select SND_SOC_AMD_ACPI_MACH
help
This options enables generic PCI driver for ACP device.
@@ -47,6 +51,7 @@ config SND_AMD_ASOC_RENOIR
select SND_SOC_AMD_ACP_I2S
select SND_SOC_AMD_ACP_PDM
select SND_SOC_AMD_ACP_LEGACY_COMMON
+ select SND_SOC_AMD_ACPI_MACH
depends on X86 && PCI
help
This option enables Renoir I2S support on AMD platform.
@@ -58,6 +63,8 @@ config SND_AMD_ASOC_REMBRANDT
select SND_SOC_AMD_ACP_I2S
select SND_SOC_AMD_ACP_PDM
select SND_SOC_AMD_ACP_LEGACY_COMMON
+ select SND_SOC_AMD_ACPI_MACH
+ depends on AMD_NODE
depends on X86 && PCI
help
This option enables Rembrandt I2S support on AMD platform.
@@ -68,10 +75,12 @@ config SND_AMD_ASOC_ACP63
tristate "AMD ACP ASOC ACP6.3 Support"
depends on X86 && PCI
depends on ACPI
+ depends on AMD_NODE
select SND_SOC_AMD_ACP_PCM
select SND_SOC_AMD_ACP_I2S
select SND_SOC_AMD_ACP_PDM
select SND_SOC_AMD_ACP_LEGACY_COMMON
+ select SND_SOC_AMD_ACPI_MACH
help
This option enables Acp6.3 I2S support on AMD platform.
Say Y if you want to enable AUDIO on ACP6.3
@@ -81,10 +90,12 @@ config SND_AMD_ASOC_ACP70
tristate "AMD ACP ASOC Acp7.0 Support"
depends on X86 && PCI
depends on ACPI
+ depends on AMD_NODE
select SND_SOC_AMD_ACP_PCM
select SND_SOC_AMD_ACP_I2S
select SND_SOC_AMD_ACP_PDM
select SND_SOC_AMD_ACP_LEGACY_COMMON
+ select SND_SOC_AMD_ACPI_MACH
help
This option enables Acp7.0 PDM support on AMD platform.
Say Y if you want to enable AUDIO on ACP7.0
@@ -156,6 +167,7 @@ config SND_SOC_AMD_LEGACY_SDW_MACH
select SND_SOC_RT712_SDCA_SDW
select SND_SOC_RT712_SDCA_DMIC_SDW
select SND_SOC_RT1316_SDW
+ select SND_SOC_RT1320_SDW
select SND_SOC_RT715_SDW
select SND_SOC_RT715_SDCA_SDW
select SND_SOC_RT722_SDCA_SDW
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index bb2702036338..08220b9a3802 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -11,6 +11,7 @@ snd-acp-pdm-y := acp-pdm.o
snd-acp-legacy-common-y := acp-legacy-common.o
snd-acp-pci-y := acp-pci.o
snd-amd-sdw-acpi-y := amd-sdw-acpi.o
+snd-amd-acpi-mach-y := amd-acpi-mach.o
#platform specific driver
snd-acp-renoir-y := acp-renoir.o
@@ -22,7 +23,7 @@ snd-acp70-y := acp70.o
snd-acp-mach-y := acp-mach-common.o
snd-acp-legacy-mach-y := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o
snd-acp-sof-mach-y := acp-sof-mach.o
-snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o
+snd-soc-acpi-amd-match-y := amd-acp63-acpi-match.o amd-acp70-acpi-match.o
snd-acp-sdw-mach-y := acp-sdw-mach-common.o
snd-acp-sdw-sof-mach-y += acp-sdw-sof-mach.o
snd-acp-sdw-legacy-mach-y += acp-sdw-legacy-mach.o
@@ -32,6 +33,7 @@ obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o
obj-$(CONFIG_SND_SOC_AMD_ACP_PDM) += snd-acp-pdm.o
obj-$(CONFIG_SND_SOC_AMD_ACP_LEGACY_COMMON) += snd-acp-legacy-common.o
obj-$(CONFIG_SND_SOC_AMD_ACP_PCI) += snd-acp-pci.o
+obj-$(CONFIG_SND_SOC_AMD_ACPI_MACH) += snd-amd-acpi-mach.o
obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
obj-$(CONFIG_SND_AMD_ASOC_REMBRANDT) += snd-acp-rembrandt.o
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c
index 89e99ed4275a..70fa54d568ef 100644
--- a/sound/soc/amd/acp/acp-i2s.c
+++ b/sound/soc/amd/acp/acp-i2s.c
@@ -31,14 +31,10 @@
#define ACP63_LRCLK_DIV_FIELD GENMASK(12, 2)
#define ACP63_BCLK_DIV_FIELD GENMASK(23, 13)
-static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id)
+static inline void acp_set_i2s_clk(struct acp_chip_info *chip, int dai_id)
{
u32 i2s_clk_reg, val;
- struct acp_chip_info *chip;
- struct device *dev;
- dev = adata->dev;
- chip = dev_get_platdata(dev);
switch (dai_id) {
case I2S_SP_INSTANCE:
i2s_clk_reg = ACP_I2STDM0_MSTRCLKGEN;
@@ -55,36 +51,37 @@ static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id)
}
val = I2S_MASTER_MODE_ENABLE;
- if (adata->tdm_mode)
+ if (chip->tdm_mode)
val |= BIT(1);
switch (chip->acp_rev) {
case ACP63_PCI_ID:
case ACP70_PCI_ID:
case ACP71_PCI_ID:
- val |= FIELD_PREP(ACP63_LRCLK_DIV_FIELD, adata->lrclk_div);
- val |= FIELD_PREP(ACP63_BCLK_DIV_FIELD, adata->bclk_div);
+ val |= FIELD_PREP(ACP63_LRCLK_DIV_FIELD, chip->lrclk_div);
+ val |= FIELD_PREP(ACP63_BCLK_DIV_FIELD, chip->bclk_div);
break;
default:
- val |= FIELD_PREP(LRCLK_DIV_FIELD, adata->lrclk_div);
- val |= FIELD_PREP(BCLK_DIV_FIELD, adata->bclk_div);
+ val |= FIELD_PREP(LRCLK_DIV_FIELD, chip->lrclk_div);
+ val |= FIELD_PREP(BCLK_DIV_FIELD, chip->bclk_div);
}
- writel(val, adata->acp_base + i2s_clk_reg);
+ writel(val, chip->base + i2s_clk_reg);
}
static int acp_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt)
{
- struct acp_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
+ struct device *dev = cpu_dai->component->dev;
+ struct acp_chip_info *chip = dev_get_platdata(dev);
int mode;
mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
switch (mode) {
case SND_SOC_DAIFMT_I2S:
- adata->tdm_mode = TDM_DISABLE;
+ chip->tdm_mode = TDM_DISABLE;
break;
case SND_SOC_DAIFMT_DSP_A:
- adata->tdm_mode = TDM_ENABLE;
+ chip->tdm_mode = TDM_ENABLE;
break;
default:
return -EINVAL;
@@ -96,12 +93,11 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas
int slots, int slot_width)
{
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = snd_soc_dai_get_drvdata(dai);
struct acp_chip_info *chip;
struct acp_stream *stream;
int slot_len, no_of_slots;
- chip = dev_get_platdata(dev);
+ chip = dev_get_drvdata(dev->parent);
switch (slot_width) {
case SLOT_WIDTH_8:
slot_len = 8;
@@ -157,35 +153,35 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas
slots = no_of_slots;
- spin_lock_irq(&adata->acp_lock);
- list_for_each_entry(stream, &adata->stream_list, list) {
+ spin_lock_irq(&chip->acp_lock);
+ list_for_each_entry(stream, &chip->stream_list, list) {
switch (chip->acp_rev) {
case ACP_RN_PCI_ID:
case ACP_RMB_PCI_ID:
if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
- adata->tdm_tx_fmt[stream->dai_id - 1] =
+ chip->tdm_tx_fmt[stream->dai_id - 1] =
FRM_LEN | (slots << 15) | (slot_len << 18);
else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE)
- adata->tdm_rx_fmt[stream->dai_id - 1] =
+ chip->tdm_rx_fmt[stream->dai_id - 1] =
FRM_LEN | (slots << 15) | (slot_len << 18);
break;
case ACP63_PCI_ID:
case ACP70_PCI_ID:
case ACP71_PCI_ID:
if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
- adata->tdm_tx_fmt[stream->dai_id - 1] =
+ chip->tdm_tx_fmt[stream->dai_id - 1] =
FRM_LEN | (slots << 13) | (slot_len << 18);
else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE)
- adata->tdm_rx_fmt[stream->dai_id - 1] =
+ chip->tdm_rx_fmt[stream->dai_id - 1] =
FRM_LEN | (slots << 13) | (slot_len << 18);
break;
default:
dev_err(dev, "Unknown chip revision %d\n", chip->acp_rev);
- spin_unlock_irq(&adata->acp_lock);
+ spin_unlock_irq(&chip->acp_lock);
return -EINVAL;
}
}
- spin_unlock_irq(&adata->acp_lock);
+ spin_unlock_irq(&chip->acp_lock);
return 0;
}
@@ -193,15 +189,15 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
struct snd_soc_dai *dai)
{
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata;
+ struct acp_chip_info *chip;
struct acp_resource *rsrc;
u32 val;
u32 xfer_resolution;
u32 reg_val, fmt_reg, tdm_fmt;
u32 lrclk_div_val, bclk_div_val;
- adata = snd_soc_dai_get_drvdata(dai);
- rsrc = adata->rsrc;
+ chip = dev_get_platdata(dev);
+ rsrc = chip->rsrc;
/* These values are as per Hardware Spec */
switch (params_format(params)) {
@@ -240,7 +236,7 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
return -EINVAL;
}
- adata->xfer_tx_resolution[dai->driver->id - 1] = xfer_resolution;
+ chip->xfer_tx_resolution[dai->driver->id - 1] = xfer_resolution;
} else {
switch (dai->driver->id) {
case I2S_BT_INSTANCE:
@@ -259,22 +255,22 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
return -EINVAL;
}
- adata->xfer_rx_resolution[dai->driver->id - 1] = xfer_resolution;
+ chip->xfer_rx_resolution[dai->driver->id - 1] = xfer_resolution;
}
- val = readl(adata->acp_base + reg_val);
+ val = readl(chip->base + reg_val);
val &= ~ACP3x_ITER_IRER_SAMP_LEN_MASK;
val = val | (xfer_resolution << 3);
- writel(val, adata->acp_base + reg_val);
+ writel(val, chip->base + reg_val);
- if (adata->tdm_mode) {
- val = readl(adata->acp_base + reg_val);
- writel(val | BIT(1), adata->acp_base + reg_val);
+ if (chip->tdm_mode) {
+ val = readl(chip->base + reg_val);
+ writel(val | BIT(1), chip->base + reg_val);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- tdm_fmt = adata->tdm_tx_fmt[dai->driver->id - 1];
+ tdm_fmt = chip->tdm_tx_fmt[dai->driver->id - 1];
else
- tdm_fmt = adata->tdm_rx_fmt[dai->driver->id - 1];
- writel(tdm_fmt, adata->acp_base + fmt_reg);
+ tdm_fmt = chip->tdm_rx_fmt[dai->driver->id - 1];
+ writel(tdm_fmt, chip->base + fmt_reg);
}
if (rsrc->soc_mclk) {
@@ -377,8 +373,8 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
default:
break;
}
- adata->lrclk_div = lrclk_div_val;
- adata->bclk_div = bclk_div_val;
+ chip->lrclk_div = lrclk_div_val;
+ chip->bclk_div = bclk_div_val;
}
return 0;
}
@@ -387,8 +383,8 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
{
struct acp_stream *stream = substream->runtime->private_data;
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
- struct acp_resource *rsrc = adata->rsrc;
+ struct acp_chip_info *chip = dev_get_platdata(dev);
+ struct acp_resource *rsrc = chip->rsrc;
u32 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg;
period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size);
@@ -398,20 +394,20 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- stream->bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream);
+ stream->bytescount = acp_get_byte_count(chip, stream->dai_id, substream->stream);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
switch (dai->driver->id) {
case I2S_BT_INSTANCE:
- water_val = ACP_BT_TX_INTR_WATERMARK_SIZE(adata);
+ water_val = ACP_BT_TX_INTR_WATERMARK_SIZE(chip);
reg_val = ACP_BTTDM_ITER;
ier_val = ACP_BTTDM_IER;
- buf_reg = ACP_BT_TX_RINGBUFSIZE(adata);
+ buf_reg = ACP_BT_TX_RINGBUFSIZE(chip);
break;
case I2S_SP_INSTANCE:
- water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE(adata);
+ water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE(chip);
reg_val = ACP_I2STDM_ITER;
ier_val = ACP_I2STDM_IER;
- buf_reg = ACP_I2S_TX_RINGBUFSIZE(adata);
+ buf_reg = ACP_I2S_TX_RINGBUFSIZE(chip);
break;
case I2S_HS_INSTANCE:
water_val = ACP_HS_TX_INTR_WATERMARK_SIZE;
@@ -426,16 +422,16 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
} else {
switch (dai->driver->id) {
case I2S_BT_INSTANCE:
- water_val = ACP_BT_RX_INTR_WATERMARK_SIZE(adata);
+ water_val = ACP_BT_RX_INTR_WATERMARK_SIZE(chip);
reg_val = ACP_BTTDM_IRER;
ier_val = ACP_BTTDM_IER;
- buf_reg = ACP_BT_RX_RINGBUFSIZE(adata);
+ buf_reg = ACP_BT_RX_RINGBUFSIZE(chip);
break;
case I2S_SP_INSTANCE:
- water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE(adata);
+ water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE(chip);
reg_val = ACP_I2STDM_IRER;
ier_val = ACP_I2STDM_IER;
- buf_reg = ACP_I2S_RX_RINGBUFSIZE(adata);
+ buf_reg = ACP_I2S_RX_RINGBUFSIZE(chip);
break;
case I2S_HS_INSTANCE:
water_val = ACP_HS_RX_INTR_WATERMARK_SIZE;
@@ -449,14 +445,14 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
}
}
- writel(period_bytes, adata->acp_base + water_val);
- writel(buf_size, adata->acp_base + buf_reg);
+ writel(period_bytes, chip->base + water_val);
+ writel(buf_size, chip->base + buf_reg);
if (rsrc->soc_mclk)
- acp_set_i2s_clk(adata, dai->driver->id);
- val = readl(adata->acp_base + reg_val);
+ acp_set_i2s_clk(chip, dai->driver->id);
+ val = readl(chip->base + reg_val);
val = val | BIT(0);
- writel(val, adata->acp_base + reg_val);
- writel(1, adata->acp_base + ier_val);
+ writel(val, chip->base + reg_val);
+ writel(1, chip->base + ier_val);
return 0;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -493,19 +489,19 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
return -EINVAL;
}
}
- val = readl(adata->acp_base + reg_val);
+ val = readl(chip->base + reg_val);
val = val & ~BIT(0);
- writel(val, adata->acp_base + reg_val);
-
- if (!(readl(adata->acp_base + ACP_BTTDM_ITER) & BIT(0)) &&
- !(readl(adata->acp_base + ACP_BTTDM_IRER) & BIT(0)))
- writel(0, adata->acp_base + ACP_BTTDM_IER);
- if (!(readl(adata->acp_base + ACP_I2STDM_ITER) & BIT(0)) &&
- !(readl(adata->acp_base + ACP_I2STDM_IRER) & BIT(0)))
- writel(0, adata->acp_base + ACP_I2STDM_IER);
- if (!(readl(adata->acp_base + ACP_HSTDM_ITER) & BIT(0)) &&
- !(readl(adata->acp_base + ACP_HSTDM_IRER) & BIT(0)))
- writel(0, adata->acp_base + ACP_HSTDM_IER);
+ writel(val, chip->base + reg_val);
+
+ if (!(readl(chip->base + ACP_BTTDM_ITER) & BIT(0)) &&
+ !(readl(chip->base + ACP_BTTDM_IRER) & BIT(0)))
+ writel(0, chip->base + ACP_BTTDM_IER);
+ if (!(readl(chip->base + ACP_I2STDM_ITER) & BIT(0)) &&
+ !(readl(chip->base + ACP_I2STDM_IRER) & BIT(0)))
+ writel(0, chip->base + ACP_I2STDM_IER);
+ if (!(readl(chip->base + ACP_HSTDM_ITER) & BIT(0)) &&
+ !(readl(chip->base + ACP_HSTDM_IRER) & BIT(0)))
+ writel(0, chip->base + ACP_HSTDM_IER);
return 0;
default:
return -EINVAL;
@@ -517,9 +513,8 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
{
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
- struct acp_chip_info *chip;
- struct acp_resource *rsrc = adata->rsrc;
+ struct acp_chip_info *chip = dev_get_platdata(dev);
+ struct acp_resource *rsrc = chip->rsrc;
struct acp_stream *stream = substream->runtime->private_data;
u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0;
u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl;
@@ -529,56 +524,56 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
switch (dai->driver->id) {
case I2S_SP_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
- reg_dma_size = ACP_I2S_TX_DMA_SIZE(adata);
+ reg_dma_size = ACP_I2S_TX_DMA_SIZE(chip);
acp_fifo_addr = rsrc->sram_pte_offset +
SP_PB_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata);
- reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata);
+ reg_fifo_addr = ACP_I2S_TX_FIFOADDR(chip);
+ reg_fifo_size = ACP_I2S_TX_FIFOSIZE(chip);
if (chip->acp_rev >= ACP70_PCI_ID)
phy_addr = ACP7x_I2S_SP_TX_MEM_WINDOW_START;
else
phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR(adata));
+ writel(phy_addr, chip->base + ACP_I2S_TX_RINGBUFADDR(chip));
} else {
- reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata);
+ reg_dma_size = ACP_I2S_RX_DMA_SIZE(chip);
acp_fifo_addr = rsrc->sram_pte_offset +
SP_CAPT_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata);
- reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata);
+ reg_fifo_addr = ACP_I2S_RX_FIFOADDR(chip);
+ reg_fifo_size = ACP_I2S_RX_FIFOSIZE(chip);
if (chip->acp_rev >= ACP70_PCI_ID)
phy_addr = ACP7x_I2S_SP_RX_MEM_WINDOW_START;
else
phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR(adata));
+ writel(phy_addr, chip->base + ACP_I2S_RX_RINGBUFADDR(chip));
}
break;
case I2S_BT_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
- reg_dma_size = ACP_BT_TX_DMA_SIZE(adata);
+ reg_dma_size = ACP_BT_TX_DMA_SIZE(chip);
acp_fifo_addr = rsrc->sram_pte_offset +
BT_PB_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata);
- reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata);
+ reg_fifo_addr = ACP_BT_TX_FIFOADDR(chip);
+ reg_fifo_size = ACP_BT_TX_FIFOSIZE(chip);
if (chip->acp_rev >= ACP70_PCI_ID)
phy_addr = ACP7x_I2S_BT_TX_MEM_WINDOW_START;
else
phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR(adata));
+ writel(phy_addr, chip->base + ACP_BT_TX_RINGBUFADDR(chip));
} else {
- reg_dma_size = ACP_BT_RX_DMA_SIZE(adata);
+ reg_dma_size = ACP_BT_RX_DMA_SIZE(chip);
acp_fifo_addr = rsrc->sram_pte_offset +
BT_CAPT_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata);
- reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata);
+ reg_fifo_addr = ACP_BT_RX_FIFOADDR(chip);
+ reg_fifo_size = ACP_BT_RX_FIFOSIZE(chip);
if (chip->acp_rev >= ACP70_PCI_ID)
phy_addr = ACP7x_I2S_BT_RX_MEM_WINDOW_START;
else
phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR(adata));
+ writel(phy_addr, chip->base + ACP_BT_RX_RINGBUFADDR(chip));
}
break;
case I2S_HS_INSTANCE:
@@ -593,7 +588,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
phy_addr = ACP7x_I2S_HS_TX_MEM_WINDOW_START;
else
phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR);
+ writel(phy_addr, chip->base + ACP_HS_TX_RINGBUFADDR);
} else {
reg_dma_size = ACP_HS_RX_DMA_SIZE;
acp_fifo_addr = rsrc->sram_pte_offset +
@@ -605,7 +600,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
phy_addr = ACP7x_I2S_HS_RX_MEM_WINDOW_START;
else
phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR);
+ writel(phy_addr, chip->base + ACP_HS_RX_RINGBUFADDR);
}
break;
default:
@@ -613,11 +608,11 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
return -EINVAL;
}
- writel(DMA_SIZE, adata->acp_base + reg_dma_size);
- writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
- writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
+ writel(DMA_SIZE, chip->base + reg_dma_size);
+ writel(acp_fifo_addr, chip->base + reg_fifo_addr);
+ writel(FIFO_SIZE, chip->base + reg_fifo_size);
- ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
+ ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used));
ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
BIT(BT_RX_THRESHOLD(rsrc->offset)) |
BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
@@ -625,7 +620,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
BIT(HS_RX_THRESHOLD(rsrc->offset)) |
BIT(HS_TX_THRESHOLD(rsrc->offset));
- writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
+ writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used));
return 0;
}
@@ -634,8 +629,8 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d
{
struct acp_stream *stream = substream->runtime->private_data;
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
- struct acp_resource *rsrc = adata->rsrc;
+ struct acp_chip_info *chip = dev_get_platdata(dev);
+ struct acp_resource *rsrc = chip->rsrc;
unsigned int dir = substream->stream;
unsigned int irq_bit = 0;
diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c
index 7acc7ed2e8cc..ba8db0851daa 100644
--- a/sound/soc/amd/acp/acp-legacy-common.c
+++ b/sound/soc/amd/acp/acp-legacy-common.c
@@ -13,32 +13,132 @@
*/
#include "amd.h"
+#include <linux/acpi.h>
#include <linux/pci.h>
#include <linux/export.h>
+#include "../mach-config.h"
+
#define ACP_RENOIR_PDM_ADDR 0x02
#define ACP_REMBRANDT_PDM_ADDR 0x03
#define ACP63_PDM_ADDR 0x02
#define ACP70_PDM_ADDR 0x02
-void acp_enable_interrupts(struct acp_dev_data *adata)
+struct acp_resource rn_rsrc = {
+ .offset = 20,
+ .no_of_ctrls = 1,
+ .irqp_used = 0,
+ .irq_reg_offset = 0x1800,
+ .scratch_reg_offset = 0x12800,
+ .sram_pte_offset = 0x02052800,
+};
+EXPORT_SYMBOL_NS_GPL(rn_rsrc, "SND_SOC_ACP_COMMON");
+
+struct acp_resource rmb_rsrc = {
+ .offset = 0,
+ .no_of_ctrls = 2,
+ .irqp_used = 1,
+ .soc_mclk = true,
+ .irq_reg_offset = 0x1a00,
+ .scratch_reg_offset = 0x12800,
+ .sram_pte_offset = 0x03802800,
+};
+EXPORT_SYMBOL_NS_GPL(rmb_rsrc, "SND_SOC_ACP_COMMON");
+
+struct acp_resource acp63_rsrc = {
+ .offset = 0,
+ .no_of_ctrls = 2,
+ .irqp_used = 1,
+ .soc_mclk = true,
+ .irq_reg_offset = 0x1a00,
+ .scratch_reg_offset = 0x12800,
+ .sram_pte_offset = 0x03802800,
+};
+EXPORT_SYMBOL_NS_GPL(acp63_rsrc, "SND_SOC_ACP_COMMON");
+
+struct acp_resource acp70_rsrc = {
+ .offset = 0,
+ .no_of_ctrls = 2,
+ .irqp_used = 1,
+ .soc_mclk = true,
+ .irq_reg_offset = 0x1a00,
+ .scratch_reg_offset = 0x10000,
+ .sram_pte_offset = 0x03800000,
+};
+EXPORT_SYMBOL_NS_GPL(acp70_rsrc, "SND_SOC_ACP_COMMON");
+
+static const struct snd_acp_hw_ops acp_common_hw_ops = {
+ /* ACP hardware initilizations */
+ .acp_init = acp_init,
+ .acp_deinit = acp_deinit,
+
+ /* ACP Interrupts*/
+ .irq = acp_irq_handler,
+ .en_interrupts = acp_enable_interrupts,
+ .dis_interrupts = acp_disable_interrupts,
+};
+
+irqreturn_t acp_irq_handler(int irq, void *data)
{
- struct acp_resource *rsrc = adata->rsrc;
+ struct acp_chip_info *chip = data;
+ struct acp_resource *rsrc = chip->rsrc;
+ struct acp_stream *stream;
+ u16 i2s_flag = 0;
+ u32 ext_intr_stat, ext_intr_stat1;
+
+ if (rsrc->no_of_ctrls == 2)
+ ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(chip, (rsrc->irqp_used - 1)));
+
+ ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used));
+
+ spin_lock(&chip->acp_lock);
+ list_for_each_entry(stream, &chip->stream_list, list) {
+ if (ext_intr_stat & stream->irq_bit) {
+ writel(stream->irq_bit,
+ ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used));
+ snd_pcm_period_elapsed(stream->substream);
+ i2s_flag = 1;
+ }
+ if (chip->rsrc->no_of_ctrls == 2) {
+ if (ext_intr_stat1 & stream->irq_bit) {
+ writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(chip,
+ (rsrc->irqp_used - 1)));
+ snd_pcm_period_elapsed(stream->substream);
+ i2s_flag = 1;
+ }
+ }
+ }
+ spin_unlock(&chip->acp_lock);
+ if (i2s_flag)
+ return IRQ_HANDLED;
+
+ return IRQ_NONE;
+}
+
+int acp_enable_interrupts(struct acp_chip_info *chip)
+{
+ struct acp_resource *rsrc;
u32 ext_intr_ctrl;
- writel(0x01, ACP_EXTERNAL_INTR_ENB(adata));
- ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
+ rsrc = chip->rsrc;
+ writel(0x01, ACP_EXTERNAL_INTR_ENB(chip));
+ ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used));
ext_intr_ctrl |= ACP_ERROR_MASK;
- writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
+ writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used));
+
+ return 0;
}
EXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, "SND_SOC_ACP_COMMON");
-void acp_disable_interrupts(struct acp_dev_data *adata)
+int acp_disable_interrupts(struct acp_chip_info *chip)
{
- struct acp_resource *rsrc = adata->rsrc;
+ struct acp_resource *rsrc;
+
+ rsrc = chip->rsrc;
+ writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(chip, rsrc->irqp_used));
+ writel(0x00, ACP_EXTERNAL_INTR_ENB(chip));
- writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
- writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
+ return 0;
}
EXPORT_SYMBOL_NS_GPL(acp_disable_interrupts, "SND_SOC_ACP_COMMON");
@@ -48,7 +148,7 @@ static void set_acp_pdm_ring_buffer(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
struct acp_stream *stream = runtime->private_data;
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_platdata(dev);
u32 physical_addr, pdm_size, period_bytes;
@@ -57,29 +157,29 @@ static void set_acp_pdm_ring_buffer(struct snd_pcm_substream *substream,
physical_addr = stream->reg_offset + MEM_WINDOW_START;
/* Init ACP PDM Ring buffer */
- writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR);
- writel(pdm_size, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE);
- writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
- writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
+ writel(physical_addr, chip->base + ACP_WOV_RX_RINGBUFADDR);
+ writel(pdm_size, chip->base + ACP_WOV_RX_RINGBUFSIZE);
+ writel(period_bytes, chip->base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
+ writel(0x01, chip->base + ACPAXI2AXI_ATU_CTRL);
}
static void set_acp_pdm_clk(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_platdata(dev);
unsigned int pdm_ctrl;
/* Enable default ACP PDM clk */
- writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL);
- pdm_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL);
+ writel(PDM_CLK_FREQ_MASK, chip->base + ACP_WOV_CLK_CTRL);
+ pdm_ctrl = readl(chip->base + ACP_WOV_MISC_CTRL);
pdm_ctrl |= PDM_MISC_CTRL_MASK;
- writel(pdm_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL);
+ writel(pdm_ctrl, chip->base + ACP_WOV_MISC_CTRL);
set_acp_pdm_ring_buffer(substream, dai);
}
void restore_acp_pdm_params(struct snd_pcm_substream *substream,
- struct acp_dev_data *adata)
+ struct acp_chip_info *chip)
{
struct snd_soc_dai *dai;
struct snd_soc_pcm_runtime *soc_runtime;
@@ -87,14 +187,15 @@ void restore_acp_pdm_params(struct snd_pcm_substream *substream,
soc_runtime = snd_soc_substream_to_rtd(substream);
dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
+
/* Programming channel mask and sampling rate */
- writel(adata->ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
- writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
+ writel(chip->ch_mask, chip->base + ACP_WOV_PDM_NO_OF_CHANNELS);
+ writel(PDM_DEC_64, chip->base + ACP_WOV_PDM_DECIMATION_FACTOR);
/* Enabling ACP Pdm interuppts */
- ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
+ ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0));
ext_int_ctrl |= PDM_DMA_INTR_MASK;
- writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
+ writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0));
set_acp_pdm_clk(substream, dai);
}
EXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, "SND_SOC_ACP_COMMON");
@@ -103,8 +204,8 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
- struct acp_resource *rsrc = adata->rsrc;
+ struct acp_chip_info *chip = dev_get_platdata(dev);
+ struct acp_resource *rsrc = chip->rsrc;
struct acp_stream *stream = substream->runtime->private_data;
u32 reg_dma_size, reg_fifo_size, reg_fifo_addr;
u32 phy_addr, acp_fifo_addr, ext_int_ctrl;
@@ -113,40 +214,40 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
switch (dai->driver->id) {
case I2S_SP_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
- reg_dma_size = ACP_I2S_TX_DMA_SIZE(adata);
+ reg_dma_size = ACP_I2S_TX_DMA_SIZE(chip);
acp_fifo_addr = rsrc->sram_pte_offset +
SP_PB_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata);
- reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata);
+ reg_fifo_addr = ACP_I2S_TX_FIFOADDR(chip);
+ reg_fifo_size = ACP_I2S_TX_FIFOSIZE(chip);
phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR(adata));
+ writel(phy_addr, chip->base + ACP_I2S_TX_RINGBUFADDR(chip));
} else {
- reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata);
+ reg_dma_size = ACP_I2S_RX_DMA_SIZE(chip);
acp_fifo_addr = rsrc->sram_pte_offset +
SP_CAPT_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata);
- reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata);
+ reg_fifo_addr = ACP_I2S_RX_FIFOADDR(chip);
+ reg_fifo_size = ACP_I2S_RX_FIFOSIZE(chip);
phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR(adata));
+ writel(phy_addr, chip->base + ACP_I2S_RX_RINGBUFADDR(chip));
}
break;
case I2S_BT_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
- reg_dma_size = ACP_BT_TX_DMA_SIZE(adata);
+ reg_dma_size = ACP_BT_TX_DMA_SIZE(chip);
acp_fifo_addr = rsrc->sram_pte_offset +
BT_PB_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata);
- reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata);
+ reg_fifo_addr = ACP_BT_TX_FIFOADDR(chip);
+ reg_fifo_size = ACP_BT_TX_FIFOSIZE(chip);
phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR(adata));
+ writel(phy_addr, chip->base + ACP_BT_TX_RINGBUFADDR(chip));
} else {
- reg_dma_size = ACP_BT_RX_DMA_SIZE(adata);
+ reg_dma_size = ACP_BT_RX_DMA_SIZE(chip);
acp_fifo_addr = rsrc->sram_pte_offset +
BT_CAPT_FIFO_ADDR_OFFSET;
- reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata);
- reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata);
+ reg_fifo_addr = ACP_BT_RX_FIFOADDR(chip);
+ reg_fifo_size = ACP_BT_RX_FIFOSIZE(chip);
phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR(adata));
+ writel(phy_addr, chip->base + ACP_BT_RX_RINGBUFADDR(chip));
}
break;
case I2S_HS_INSTANCE:
@@ -157,7 +258,7 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
reg_fifo_addr = ACP_HS_TX_FIFOADDR;
reg_fifo_size = ACP_HS_TX_FIFOSIZE;
phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR);
+ writel(phy_addr, chip->base + ACP_HS_TX_RINGBUFADDR);
} else {
reg_dma_size = ACP_HS_RX_DMA_SIZE;
acp_fifo_addr = rsrc->sram_pte_offset +
@@ -165,7 +266,7 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
reg_fifo_addr = ACP_HS_RX_FIFOADDR;
reg_fifo_size = ACP_HS_RX_FIFOSIZE;
phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
- writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR);
+ writel(phy_addr, chip->base + ACP_HS_RX_RINGBUFADDR);
}
break;
default:
@@ -173,11 +274,11 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
return -EINVAL;
}
- writel(DMA_SIZE, adata->acp_base + reg_dma_size);
- writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
- writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
+ writel(DMA_SIZE, chip->base + reg_dma_size);
+ writel(acp_fifo_addr, chip->base + reg_fifo_addr);
+ writel(FIFO_SIZE, chip->base + reg_fifo_size);
- ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
+ ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used));
ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
BIT(BT_RX_THRESHOLD(rsrc->offset)) |
BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
@@ -185,12 +286,12 @@ static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
BIT(HS_RX_THRESHOLD(rsrc->offset)) |
BIT(HS_TX_THRESHOLD(rsrc->offset));
- writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
+ writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, rsrc->irqp_used));
return 0;
}
int restore_acp_i2s_params(struct snd_pcm_substream *substream,
- struct acp_dev_data *adata,
+ struct acp_chip_info *chip,
struct acp_stream *stream)
{
struct snd_soc_dai *dai;
@@ -200,7 +301,7 @@ int restore_acp_i2s_params(struct snd_pcm_substream *substream,
soc_runtime = snd_soc_substream_to_rtd(substream);
dai = snd_soc_rtd_to_cpu(soc_runtime, 0);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- tdm_fmt = adata->tdm_tx_fmt[stream->dai_id - 1];
+ tdm_fmt = chip->tdm_tx_fmt[stream->dai_id - 1];
switch (stream->dai_id) {
case I2S_BT_INSTANCE:
reg_val = ACP_BTTDM_ITER;
@@ -218,9 +319,9 @@ int restore_acp_i2s_params(struct snd_pcm_substream *substream,
pr_err("Invalid dai id %x\n", stream->dai_id);
return -EINVAL;
}
- val = adata->xfer_tx_resolution[stream->dai_id - 1] << 3;
+ val = chip->xfer_tx_resolution[stream->dai_id - 1] << 3;
} else {
- tdm_fmt = adata->tdm_rx_fmt[stream->dai_id - 1];
+ tdm_fmt = chip->tdm_rx_fmt[stream->dai_id - 1];
switch (stream->dai_id) {
case I2S_BT_INSTANCE:
reg_val = ACP_BTTDM_IRER;
@@ -238,13 +339,13 @@ int restore_acp_i2s_params(struct snd_pcm_substream *substream,
pr_err("Invalid dai id %x\n", stream->dai_id);
return -EINVAL;
}
- val = adata->xfer_rx_resolution[stream->dai_id - 1] << 3;
+ val = chip->xfer_rx_resolution[stream->dai_id - 1] << 3;
}
- writel(val, adata->acp_base + reg_val);
- if (adata->tdm_mode == TDM_ENABLE) {
- writel(tdm_fmt, adata->acp_base + fmt_reg);
- val = readl(adata->acp_base + reg_val);
- writel(val | 0x2, adata->acp_base + reg_val);
+ writel(val, chip->base + reg_val);
+ if (chip->tdm_mode == TDM_ENABLE) {
+ writel(tdm_fmt, chip->base + fmt_reg);
+ val = readl(chip->base + reg_val);
+ writel(val | 0x2, chip->base + reg_val);
}
return set_acp_i2s_dma_fifo(substream, dai);
}
@@ -344,24 +445,32 @@ int acp_deinit(struct acp_chip_info *chip)
return 0;
}
EXPORT_SYMBOL_NS_GPL(acp_deinit, "SND_SOC_ACP_COMMON");
-
-int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data)
+int acp_machine_select(struct acp_chip_info *chip)
{
- pci_write_config_dword(dev, 0x60, smn_addr);
- pci_write_config_dword(dev, 0x64, data);
+ struct snd_soc_acpi_mach *mach;
+ int size, platform;
+
+ if (chip->flag == FLAG_AMD_LEGACY_ONLY_DMIC && chip->is_pdm_dev) {
+ platform = chip->acp_rev;
+ chip->mach_dev = platform_device_register_data(chip->dev, "acp-pdm-mach",
+ PLATFORM_DEVID_NONE, &platform,
+ sizeof(platform));
+ } else {
+ size = sizeof(*chip->machines);
+ mach = snd_soc_acpi_find_machine(chip->machines);
+ if (!mach) {
+ dev_err(chip->dev, "warning: No matching ASoC machine driver found\n");
+ return -EINVAL;
+ }
+ mach->mach_params.subsystem_rev = chip->acp_rev;
+ chip->mach_dev = platform_device_register_data(chip->dev, mach->drv_name,
+ PLATFORM_DEVID_NONE, mach, size);
+ }
+ if (IS_ERR(chip->mach_dev))
+ dev_warn(chip->dev, "Unable to register Machine device\n");
return 0;
}
-EXPORT_SYMBOL_NS_GPL(smn_write, "SND_SOC_ACP_COMMON");
-
-int smn_read(struct pci_dev *dev, u32 smn_addr)
-{
- u32 data;
-
- pci_write_config_dword(dev, 0x60, smn_addr);
- pci_read_config_dword(dev, 0x64, &data);
- return data;
-}
-EXPORT_SYMBOL_NS_GPL(smn_read, "SND_SOC_ACP_COMMON");
+EXPORT_SYMBOL_NS_GPL(acp_machine_select, "SND_SOC_ACP_COMMON");
static void check_acp3x_config(struct acp_chip_info *chip)
{
@@ -445,7 +554,9 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip)
{
struct acpi_device *pdm_dev;
const union acpi_object *obj;
- u32 pdm_addr;
+ acpi_handle handle;
+ acpi_integer dmic_status;
+ u32 pdm_addr, ret;
switch (chip->acp_rev) {
case ACP_RN_PCI_ID:
@@ -477,9 +588,58 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip)
obj->integer.value == pdm_addr)
chip->is_pdm_dev = true;
}
+
+ handle = ACPI_HANDLE(&pci->dev);
+ ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status);
+ if (!ACPI_FAILURE(ret))
+ chip->is_pdm_dev = dmic_status;
}
}
EXPORT_SYMBOL_NS_GPL(check_acp_config, "SND_SOC_ACP_COMMON");
+struct snd_acp_hw_ops acp31_common_hw_ops;
+EXPORT_SYMBOL_NS_GPL(acp31_common_hw_ops, "SND_SOC_ACP_COMMON");
+int acp31_hw_ops_init(struct acp_chip_info *chip)
+{
+ memcpy(&acp31_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops));
+ chip->acp_hw_ops = &acp31_common_hw_ops;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(acp31_hw_ops_init, "SND_SOC_ACP_COMMON");
+
+struct snd_acp_hw_ops acp6x_common_hw_ops;
+EXPORT_SYMBOL_NS_GPL(acp6x_common_hw_ops, "SND_SOC_ACP_COMMON");
+int acp6x_hw_ops_init(struct acp_chip_info *chip)
+{
+ memcpy(&acp6x_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops));
+ chip->acp_hw_ops = &acp6x_common_hw_ops;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(acp6x_hw_ops_init, "SND_SOC_ACP_COMMON");
+
+struct snd_acp_hw_ops acp63_common_hw_ops;
+EXPORT_SYMBOL_NS_GPL(acp63_common_hw_ops, "SND_SOC_ACP_COMMON");
+int acp63_hw_ops_init(struct acp_chip_info *chip)
+{
+ memcpy(&acp63_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops));
+ chip->acp_hw_ops = &acp63_common_hw_ops;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(acp63_hw_ops_init, "SND_SOC_ACP_COMMON");
+
+struct snd_acp_hw_ops acp70_common_hw_ops;
+EXPORT_SYMBOL_NS_GPL(acp70_common_hw_ops, "SND_SOC_ACP_COMMON");
+int acp70_hw_ops_init(struct acp_chip_info *chip)
+{
+ memcpy(&acp70_common_hw_ops, &acp_common_hw_ops, sizeof(acp_common_hw_ops));
+ chip->acp_hw_ops = &acp70_common_hw_ops;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(acp70_hw_ops_init, "SND_SOC_ACP_COMMON");
+
MODULE_DESCRIPTION("AMD ACP legacy common features");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
index f7602c1769bf..a0dab85088ec 100644
--- a/sound/soc/amd/acp/acp-mach-common.c
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -919,7 +919,7 @@ static int acp_max98388_hw_params(struct snd_pcm_substream *substream,
int ret;
ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_CBS_CFS | SND_SOC_DAIFMT_I2S |
+ SND_SOC_DAIFMT_CBC_CFC | SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF);
if (ret < 0)
return ret;
diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
index e0fc42d939d3..0b2aa33cc426 100644
--- a/sound/soc/amd/acp/acp-pci.c
+++ b/sound/soc/amd/acp/acp-pci.c
@@ -26,32 +26,88 @@
#define ACP3x_REG_START 0x1240000
#define ACP3x_REG_END 0x125C000
-static struct platform_device *dmic_dev;
-static struct platform_device *pdev;
-
-static const struct resource acp_res[] = {
- {
- .start = 0,
- .end = ACP3x_REG_END - ACP3x_REG_START,
- .name = "acp_mem",
- .flags = IORESOURCE_MEM,
- },
- {
- .start = 0,
- .end = 0,
- .name = "acp_dai_irq",
- .flags = IORESOURCE_IRQ,
- },
-};
+static irqreturn_t irq_handler(int irq, void *data)
+{
+ struct acp_chip_info *chip = data;
-static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ if (chip && chip->acp_hw_ops && chip->acp_hw_ops->irq)
+ return chip->acp_hw_ops->irq(irq, chip);
+
+ return IRQ_NONE;
+}
+static void acp_fill_platform_dev_info(struct platform_device_info *pdevinfo,
+ struct device *parent,
+ struct fwnode_handle *fw_node,
+ char *name, unsigned int id,
+ const struct resource *res,
+ unsigned int num_res,
+ const void *data,
+ size_t size_data)
+{
+ pdevinfo->name = name;
+ pdevinfo->id = id;
+ pdevinfo->parent = parent;
+ pdevinfo->num_res = num_res;
+ pdevinfo->res = res;
+ pdevinfo->data = data;
+ pdevinfo->size_data = size_data;
+ pdevinfo->fwnode = fw_node;
+}
+
+static int create_acp_platform_devs(struct pci_dev *pci, struct acp_chip_info *chip, u32 addr)
{
struct platform_device_info pdevinfo;
+ struct device *parent;
+ int ret;
+
+ parent = &pci->dev;
+
+ if (chip->is_i2s_config || chip->is_pdm_dev) {
+ chip->res = devm_kzalloc(&pci->dev, sizeof(struct resource), GFP_KERNEL);
+ if (!chip->res) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ chip->res->flags = IORESOURCE_MEM;
+ chip->res->start = addr;
+ chip->res->end = addr + (ACP3x_REG_END - ACP3x_REG_START);
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+ }
+
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+ acp_fill_platform_dev_info(&pdevinfo, parent, NULL, chip->name,
+ 0, chip->res, 1, chip, sizeof(*chip));
+
+ chip->acp_plat_dev = platform_device_register_full(&pdevinfo);
+ if (IS_ERR(chip->acp_plat_dev)) {
+ dev_err(&pci->dev,
+ "cannot register %s device\n", pdevinfo.name);
+ ret = PTR_ERR(chip->acp_plat_dev);
+ goto err;
+ }
+ if (chip->is_pdm_dev && chip->is_pdm_config) {
+ chip->dmic_codec_dev = platform_device_register_data(&pci->dev,
+ "dmic-codec",
+ PLATFORM_DEVID_NONE,
+ NULL, 0);
+ if (IS_ERR(chip->dmic_codec_dev)) {
+ dev_err(&pci->dev, "failed to create DMIC device\n");
+ ret = PTR_ERR(chip->dmic_codec_dev);
+ goto unregister_acp_plat_dev;
+ }
+ }
+ return 0;
+unregister_acp_plat_dev:
+ platform_device_unregister(chip->acp_plat_dev);
+err:
+ return ret;
+}
+
+static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+{
struct device *dev = &pci->dev;
- const struct resource *res_acp;
struct acp_chip_info *chip;
- struct resource *res;
- unsigned int flag, addr, num_res, i;
+ unsigned int flag, addr;
int ret;
flag = snd_amd_acp_find_config(pci);
@@ -75,24 +131,32 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
pci_set_master(pci);
- res_acp = acp_res;
- num_res = ARRAY_SIZE(acp_res);
chip->acp_rev = pci->revision;
switch (pci->revision) {
case 0x01:
chip->name = "acp_asoc_renoir";
+ chip->rsrc = &rn_rsrc;
+ chip->acp_hw_ops_init = acp31_hw_ops_init;
+ chip->machines = &snd_soc_acpi_amd_acp_machines;
break;
case 0x6f:
chip->name = "acp_asoc_rembrandt";
+ chip->rsrc = &rmb_rsrc;
+ chip->acp_hw_ops_init = acp6x_hw_ops_init;
+ chip->machines = &snd_soc_acpi_amd_rmb_acp_machines;
break;
case 0x63:
chip->name = "acp_asoc_acp63";
+ chip->rsrc = &acp63_rsrc;
+ chip->acp_hw_ops_init = acp63_hw_ops_init;
+ chip->machines = &snd_soc_acpi_amd_acp63_acp_machines;
break;
case 0x70:
- chip->name = "acp_asoc_acp70";
- break;
case 0x71:
chip->name = "acp_asoc_acp70";
+ chip->rsrc = &acp70_rsrc;
+ chip->acp_hw_ops_init = acp70_hw_ops_init;
+ chip->machines = &snd_soc_acpi_amd_acp70_acp_machines;
break;
default:
dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision);
@@ -100,64 +164,46 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
goto release_regions;
}
chip->flag = flag;
- dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
- if (IS_ERR(dmic_dev)) {
- dev_err(dev, "failed to create DMIC device\n");
- ret = PTR_ERR(dmic_dev);
- goto release_regions;
- }
addr = pci_resource_start(pci, 0);
chip->base = devm_ioremap(&pci->dev, addr, pci_resource_len(pci, 0));
if (!chip->base) {
ret = -ENOMEM;
- goto unregister_dmic_dev;
+ goto release_regions;
}
- ret = acp_init(chip);
+ chip->addr = addr;
+
+ chip->acp_hw_ops_init(chip);
+ ret = acp_hw_init(chip);
if (ret)
- goto unregister_dmic_dev;
+ goto release_regions;
+
+ ret = devm_request_irq(dev, pci->irq, irq_handler,
+ IRQF_SHARED, "ACP_I2S_IRQ", chip);
+ if (ret) {
+ dev_err(&pci->dev, "ACP I2S IRQ request failed %d\n", ret);
+ goto de_init;
+ }
check_acp_config(pci, chip);
if (!chip->is_pdm_dev && !chip->is_i2s_config)
goto skip_pdev_creation;
- res = devm_kcalloc(&pci->dev, num_res, sizeof(struct resource), GFP_KERNEL);
- if (!res) {
- ret = -ENOMEM;
- goto unregister_dmic_dev;
+ ret = create_acp_platform_devs(pci, chip, addr);
+ if (ret < 0) {
+ dev_err(&pci->dev, "ACP platform devices creation failed\n");
+ goto de_init;
}
- for (i = 0; i < num_res; i++, res_acp++) {
- res[i].name = res_acp->name;
- res[i].flags = res_acp->flags;
- res[i].start = addr + res_acp->start;
- res[i].end = addr + res_acp->end;
- if (res_acp->flags == IORESOURCE_IRQ) {
- res[i].start = pci->irq;
- res[i].end = res[i].start;
- }
- }
+ chip->chip_pdev = chip->acp_plat_dev;
+ chip->dev = &chip->acp_plat_dev->dev;
- memset(&pdevinfo, 0, sizeof(pdevinfo));
-
- pdevinfo.name = chip->name;
- pdevinfo.id = 0;
- pdevinfo.parent = &pci->dev;
- pdevinfo.num_res = num_res;
- pdevinfo.res = &res[0];
- pdevinfo.data = chip;
- pdevinfo.size_data = sizeof(*chip);
-
- pdev = platform_device_register_full(&pdevinfo);
- if (IS_ERR(pdev)) {
- dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name);
- ret = PTR_ERR(pdev);
- goto unregister_dmic_dev;
- }
+ acp_machine_select(chip);
+ INIT_LIST_HEAD(&chip->stream_list);
+ spin_lock_init(&chip->acp_lock);
skip_pdev_creation:
- chip->chip_pdev = pdev;
dev_set_drvdata(&pci->dev, chip);
pm_runtime_set_autosuspend_delay(&pci->dev, 2000);
pm_runtime_use_autosuspend(&pci->dev);
@@ -165,8 +211,8 @@ skip_pdev_creation:
pm_runtime_allow(&pci->dev);
return ret;
-unregister_dmic_dev:
- platform_device_unregister(dmic_dev);
+de_init:
+ acp_hw_deinit(chip);
release_regions:
pci_release_regions(pci);
disable_pci:
@@ -175,41 +221,38 @@ disable_pci:
return ret;
};
-static int __maybe_unused snd_acp_suspend(struct device *dev)
+static int snd_acp_suspend(struct device *dev)
{
struct acp_chip_info *chip;
int ret;
chip = dev_get_drvdata(dev);
- ret = acp_deinit(chip);
+ ret = acp_hw_deinit(chip);
if (ret)
dev_err(dev, "ACP de-init failed\n");
return ret;
}
-static int __maybe_unused snd_acp_resume(struct device *dev)
+static int snd_acp_resume(struct device *dev)
{
struct acp_chip_info *chip;
- struct acp_dev_data *adata;
- struct device child;
int ret;
chip = dev_get_drvdata(dev);
- ret = acp_init(chip);
+ ret = acp_hw_init(chip);
if (ret)
dev_err(dev, "ACP init failed\n");
- if (chip->chip_pdev) {
- child = chip->chip_pdev->dev;
- adata = dev_get_drvdata(&child);
- if (adata)
- acp_enable_interrupts(adata);
- }
+
+ ret = acp_hw_en_interrupts(chip);
+ if (ret)
+ dev_err(dev, "ACP en-interrupts failed\n");
+
return ret;
}
static const struct dev_pm_ops acp_pm_ops = {
- SET_RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume)
+ RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume)
};
static void acp_pci_remove(struct pci_dev *pci)
@@ -220,11 +263,14 @@ static void acp_pci_remove(struct pci_dev *pci)
chip = pci_get_drvdata(pci);
pm_runtime_forbid(&pci->dev);
pm_runtime_get_noresume(&pci->dev);
- if (dmic_dev)
- platform_device_unregister(dmic_dev);
- if (pdev)
- platform_device_unregister(pdev);
- ret = acp_deinit(chip);
+ if (chip->dmic_codec_dev)
+ platform_device_unregister(chip->dmic_codec_dev);
+ if (chip->acp_plat_dev)
+ platform_device_unregister(chip->acp_plat_dev);
+ if (chip->mach_dev)
+ platform_device_unregister(chip->mach_dev);
+
+ ret = acp_hw_deinit(chip);
if (ret)
dev_err(&pci->dev, "ACP de-init failed\n");
}
@@ -243,7 +289,7 @@ static struct pci_driver snd_amd_acp_pci_driver = {
.probe = acp_pci_probe,
.remove = acp_pci_remove,
.driver = {
- .pm = &acp_pm_ops,
+ .pm = pm_ptr(&acp_pm_ops),
},
};
module_pci_driver(snd_amd_acp_pci_driver);
diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c
index d4855da05b6a..1bfc34c2aa53 100644
--- a/sound/soc/amd/acp/acp-pdm.c
+++ b/sound/soc/amd/acp/acp-pdm.c
@@ -30,17 +30,16 @@ static int acp_dmic_prepare(struct snd_pcm_substream *substream,
{
struct acp_stream *stream = substream->runtime->private_data;
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
struct acp_chip_info *chip;
u32 physical_addr, size_dmic, period_bytes;
unsigned int dmic_ctrl;
chip = dev_get_platdata(dev);
/* Enable default DMIC clk */
- writel(PDM_CLK_FREQ_MASK, adata->acp_base + ACP_WOV_CLK_CTRL);
- dmic_ctrl = readl(adata->acp_base + ACP_WOV_MISC_CTRL);
+ writel(PDM_CLK_FREQ_MASK, chip->base + ACP_WOV_CLK_CTRL);
+ dmic_ctrl = readl(chip->base + ACP_WOV_MISC_CTRL);
dmic_ctrl |= PDM_MISC_CTRL_MASK;
- writel(dmic_ctrl, adata->acp_base + ACP_WOV_MISC_CTRL);
+ writel(dmic_ctrl, chip->base + ACP_WOV_MISC_CTRL);
period_bytes = frames_to_bytes(substream->runtime,
substream->runtime->period_size);
@@ -53,10 +52,10 @@ static int acp_dmic_prepare(struct snd_pcm_substream *substream,
physical_addr = stream->reg_offset + MEM_WINDOW_START;
/* Init DMIC Ring buffer */
- writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR);
- writel(size_dmic, adata->acp_base + ACP_WOV_RX_RINGBUFSIZE);
- writel(period_bytes, adata->acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
- writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
+ writel(physical_addr, chip->base + ACP_WOV_RX_RINGBUFADDR);
+ writel(size_dmic, chip->base + ACP_WOV_RX_RINGBUFSIZE);
+ writel(period_bytes, chip->base + ACP_WOV_RX_INTR_WATERMARK_SIZE);
+ writel(0x01, chip->base + ACPAXI2AXI_ATU_CTRL);
return 0;
}
@@ -65,7 +64,7 @@ static int acp_dmic_dai_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_platdata(dev);
unsigned int dma_enable;
int ret = 0;
@@ -73,27 +72,27 @@ static int acp_dmic_dai_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
+ dma_enable = readl(chip->base + ACP_WOV_PDM_DMA_ENABLE);
if (!(dma_enable & DMA_EN_MASK)) {
- writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
- writel(PDM_ENABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
+ writel(PDM_ENABLE, chip->base + ACP_WOV_PDM_ENABLE);
+ writel(PDM_ENABLE, chip->base + ACP_WOV_PDM_DMA_ENABLE);
}
- ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
+ ret = readl_poll_timeout_atomic(chip->base + ACP_WOV_PDM_DMA_ENABLE,
dma_enable, (dma_enable & DMA_EN_MASK),
DELAY_US, PDM_TIMEOUT);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- dma_enable = readl(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
+ dma_enable = readl(chip->base + ACP_WOV_PDM_DMA_ENABLE);
if ((dma_enable & DMA_EN_MASK)) {
- writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_ENABLE);
- writel(PDM_DISABLE, adata->acp_base + ACP_WOV_PDM_DMA_ENABLE);
+ writel(PDM_DISABLE, chip->base + ACP_WOV_PDM_ENABLE);
+ writel(PDM_DISABLE, chip->base + ACP_WOV_PDM_DMA_ENABLE);
}
- ret = readl_poll_timeout_atomic(adata->acp_base + ACP_WOV_PDM_DMA_ENABLE,
+ ret = readl_poll_timeout_atomic(chip->base + ACP_WOV_PDM_DMA_ENABLE,
dma_enable, !(dma_enable & DMA_EN_MASK),
DELAY_US, PDM_TIMEOUT);
break;
@@ -109,7 +108,7 @@ static int acp_dmic_hwparams(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hwparams, struct snd_soc_dai *dai)
{
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_platdata(dev);
unsigned int channels, ch_mask;
channels = params_channels(hwparams);
@@ -128,14 +127,14 @@ static int acp_dmic_hwparams(struct snd_pcm_substream *substream,
return -EINVAL;
}
- adata->ch_mask = ch_mask;
+ chip->ch_mask = ch_mask;
if (params_format(hwparams) != SNDRV_PCM_FORMAT_S32_LE) {
dev_err(dai->dev, "Invalid format:%d\n", params_format(hwparams));
return -EINVAL;
}
- writel(ch_mask, adata->acp_base + ACP_WOV_PDM_NO_OF_CHANNELS);
- writel(PDM_DEC_64, adata->acp_base + ACP_WOV_PDM_DECIMATION_FACTOR);
+ writel(ch_mask, chip->base + ACP_WOV_PDM_NO_OF_CHANNELS);
+ writel(PDM_DEC_64, chip->base + ACP_WOV_PDM_DECIMATION_FACTOR);
return 0;
}
@@ -145,7 +144,7 @@ static int acp_dmic_dai_startup(struct snd_pcm_substream *substream,
{
struct acp_stream *stream = substream->runtime->private_data;
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_platdata(dev);
u32 ext_int_ctrl;
stream->dai_id = DMIC_INSTANCE;
@@ -154,9 +153,9 @@ static int acp_dmic_dai_startup(struct snd_pcm_substream *substream,
stream->reg_offset = ACP_REGION2_OFFSET;
/* Enable DMIC Interrupts */
- ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
+ ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0));
ext_int_ctrl |= PDM_DMA_INTR_MASK;
- writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
+ writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0));
return 0;
}
@@ -165,13 +164,13 @@ static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct device *dev = dai->component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_platdata(dev);
u32 ext_int_ctrl;
/* Disable DMIC interrupts */
- ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
+ ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(chip, 0));
ext_int_ctrl &= ~PDM_DMA_INTR_MASK;
- writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
+ writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(chip, 0));
}
const struct snd_soc_dai_ops acp_dmic_dai_ops = {
diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c
index aa330aeeb301..b3eddf76aaa4 100644
--- a/sound/soc/amd/acp/acp-platform.c
+++ b/sound/soc/amd/acp/acp-platform.c
@@ -21,7 +21,6 @@
#include <linux/dma-mapping.h>
#include "amd.h"
-#include "../mach-config.h"
#include "acp-mach.h"
#define DRV_NAME "acp_i2s_dma"
@@ -108,101 +107,37 @@ static const struct snd_pcm_hardware acp6x_pcm_hardware_capture = {
.periods_max = CAPTURE_MAX_NUM_PERIODS,
};
-int acp_machine_select(struct acp_dev_data *adata)
+void config_pte_for_stream(struct acp_chip_info *chip, struct acp_stream *stream)
{
- struct snd_soc_acpi_mach *mach;
- int size, platform;
-
- if (adata->flag == FLAG_AMD_LEGACY_ONLY_DMIC) {
- platform = adata->acp_rev;
- adata->mach_dev = platform_device_register_data(adata->dev, "acp-pdm-mach",
- PLATFORM_DEVID_NONE, &platform,
- sizeof(platform));
- } else {
- size = sizeof(*adata->machines);
- mach = snd_soc_acpi_find_machine(adata->machines);
- if (!mach) {
- dev_err(adata->dev, "warning: No matching ASoC machine driver found\n");
- return -EINVAL;
- }
- mach->mach_params.subsystem_rev = adata->acp_rev;
- adata->mach_dev = platform_device_register_data(adata->dev, mach->drv_name,
- PLATFORM_DEVID_NONE, mach, size);
- }
- if (IS_ERR(adata->mach_dev))
- dev_warn(adata->dev, "Unable to register Machine device\n");
- return 0;
-}
-EXPORT_SYMBOL_NS_GPL(acp_machine_select, "SND_SOC_ACP_COMMON");
-
-static irqreturn_t i2s_irq_handler(int irq, void *data)
-{
- struct acp_dev_data *adata = data;
- struct acp_resource *rsrc = adata->rsrc;
- struct acp_stream *stream;
- u16 i2s_flag = 0;
- u32 ext_intr_stat, ext_intr_stat1;
-
- if (adata->rsrc->no_of_ctrls == 2)
- ext_intr_stat1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1)));
-
- ext_intr_stat = readl(ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
-
- spin_lock(&adata->acp_lock);
- list_for_each_entry(stream, &adata->stream_list, list) {
- if (ext_intr_stat & stream->irq_bit) {
- writel(stream->irq_bit,
- ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
- snd_pcm_period_elapsed(stream->substream);
- i2s_flag = 1;
- }
- if (adata->rsrc->no_of_ctrls == 2) {
- if (ext_intr_stat1 & stream->irq_bit) {
- writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(adata,
- (rsrc->irqp_used - 1)));
- snd_pcm_period_elapsed(stream->substream);
- i2s_flag = 1;
- }
- }
- }
- spin_unlock(&adata->acp_lock);
- if (i2s_flag)
- return IRQ_HANDLED;
-
- return IRQ_NONE;
-}
-
-void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream)
-{
- struct acp_resource *rsrc = adata->rsrc;
+ struct acp_resource *rsrc = chip->rsrc;
u32 reg_val;
reg_val = rsrc->sram_pte_offset;
stream->reg_offset = 0x02000000;
- writel((reg_val + GRP1_OFFSET) | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
- writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
+ writel((reg_val + GRP1_OFFSET) | BIT(31), chip->base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
+ writel(PAGE_SIZE_4K_ENABLE, chip->base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
- writel((reg_val + GRP2_OFFSET) | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2);
- writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2);
+ writel((reg_val + GRP2_OFFSET) | BIT(31), chip->base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_2);
+ writel(PAGE_SIZE_4K_ENABLE, chip->base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2);
- writel(reg_val | BIT(31), adata->acp_base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_5);
- writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5);
+ writel(reg_val | BIT(31), chip->base + ACPAXI2AXI_ATU_BASE_ADDR_GRP_5);
+ writel(PAGE_SIZE_4K_ENABLE, chip->base + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5);
- writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
+ writel(0x01, chip->base + ACPAXI2AXI_ATU_CTRL);
}
EXPORT_SYMBOL_NS_GPL(config_pte_for_stream, "SND_SOC_ACP_COMMON");
-void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int size)
+void config_acp_dma(struct acp_chip_info *chip, struct acp_stream *stream, int size)
{
struct snd_pcm_substream *substream = stream->substream;
- struct acp_resource *rsrc = adata->rsrc;
+ struct acp_resource *rsrc = chip->rsrc;
dma_addr_t addr = substream->dma_buffer.addr;
int num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
u32 low, high, val;
u16 page_idx;
- switch (adata->acp_rev) {
+ switch (chip->acp_rev) {
case ACP70_PCI_ID:
case ACP71_PCI_ID:
switch (stream->dai_id) {
@@ -228,7 +163,7 @@ void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int s
val = 0x6000;
break;
default:
- dev_err(adata->dev, "Invalid dai id %x\n", stream->dai_id);
+ dev_err(chip->dev, "Invalid dai id %x\n", stream->dai_id);
return;
}
break;
@@ -241,9 +176,9 @@ void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int s
/* Load the low address of page int ACP SRAM through SRBM */
low = lower_32_bits(addr);
high = upper_32_bits(addr);
- writel(low, adata->acp_base + rsrc->scratch_reg_offset + val);
+ writel(low, chip->base + rsrc->scratch_reg_offset + val);
high |= BIT(31);
- writel(high, adata->acp_base + rsrc->scratch_reg_offset + val + 4);
+ writel(high, chip->base + rsrc->scratch_reg_offset + val + 4);
/* Move to next physically contiguous page */
val += 8;
@@ -256,7 +191,6 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct device *dev = component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
struct acp_chip_info *chip;
struct acp_stream *stream;
int ret;
@@ -266,7 +200,7 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
return -ENOMEM;
stream->substream = substream;
- chip = dev_get_platdata(dev);
+ chip = dev_get_drvdata(dev->parent);
switch (chip->acp_rev) {
case ACP63_PCI_ID:
case ACP70_PCI_ID:
@@ -306,11 +240,11 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
}
runtime->private_data = stream;
- writel(1, ACP_EXTERNAL_INTR_ENB(adata));
+ writel(1, ACP_EXTERNAL_INTR_ENB(chip));
- spin_lock_irq(&adata->acp_lock);
- list_add_tail(&stream->list, &adata->stream_list);
- spin_unlock_irq(&adata->acp_lock);
+ spin_lock_irq(&chip->acp_lock);
+ list_add_tail(&stream->list, &chip->stream_list);
+ spin_unlock_irq(&chip->acp_lock);
return ret;
}
@@ -319,13 +253,14 @@ static int acp_dma_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct acp_dev_data *adata = snd_soc_component_get_drvdata(component);
+ struct device *dev = component->dev;
+ struct acp_chip_info *chip = dev_get_drvdata(dev->parent);
struct acp_stream *stream = substream->runtime->private_data;
u64 size = params_buffer_bytes(params);
/* Configure ACP DMA block with params */
- config_pte_for_stream(adata, stream);
- config_acp_dma(adata, stream, size);
+ config_pte_for_stream(chip, stream);
+ config_acp_dma(chip, stream, size);
return 0;
}
@@ -334,7 +269,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct device *dev = component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_drvdata(dev->parent);
struct acp_stream *stream = substream->runtime->private_data;
u32 pos, buffersize;
u64 bytescount;
@@ -342,7 +277,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component,
buffersize = frames_to_bytes(substream->runtime,
substream->runtime->buffer_size);
- bytescount = acp_get_byte_count(adata, stream->dai_id, substream->stream);
+ bytescount = acp_get_byte_count(chip, stream->dai_id, substream->stream);
if (bytescount > stream->bytescount)
bytescount -= stream->bytescount;
@@ -366,13 +301,13 @@ static int acp_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct device *dev = component->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_drvdata(dev->parent);
struct acp_stream *stream = substream->runtime->private_data;
/* Remove entry from list */
- spin_lock_irq(&adata->acp_lock);
+ spin_lock_irq(&chip->acp_lock);
list_del(&stream->list);
- spin_unlock_irq(&adata->acp_lock);
+ spin_unlock_irq(&chip->acp_lock);
kfree(stream);
return 0;
@@ -390,38 +325,30 @@ static const struct snd_soc_component_driver acp_pcm_component = {
int acp_platform_register(struct device *dev)
{
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip;
struct snd_soc_dai_driver;
unsigned int status;
- status = devm_request_irq(dev, adata->i2s_irq, i2s_irq_handler,
- IRQF_SHARED, "ACP_I2S_IRQ", adata);
- if (status) {
- dev_err(dev, "ACP I2S IRQ request failed\n");
- return status;
+ chip = dev_get_platdata(dev);
+ if (!chip || !chip->base) {
+ dev_err(dev, "ACP chip data is NULL\n");
+ return -ENODEV;
}
status = devm_snd_soc_register_component(dev, &acp_pcm_component,
- adata->dai_driver,
- adata->num_dai);
+ chip->dai_driver,
+ chip->num_dai);
if (status) {
dev_err(dev, "Fail to register acp i2s component\n");
return status;
}
- INIT_LIST_HEAD(&adata->stream_list);
- spin_lock_init(&adata->acp_lock);
-
return 0;
}
EXPORT_SYMBOL_NS_GPL(acp_platform_register, "SND_SOC_ACP_COMMON");
int acp_platform_unregister(struct device *dev)
{
- struct acp_dev_data *adata = dev_get_drvdata(dev);
-
- if (adata->mach_dev)
- platform_device_unregister(adata->mach_dev);
return 0;
}
EXPORT_SYMBOL_NS_GPL(acp_platform_unregister, "SND_SOC_ACP_COMMON");
diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c
index 2648256fa129..aeffd24710e7 100644
--- a/sound/soc/amd/acp/acp-rembrandt.c
+++ b/sound/soc/amd/acp/acp-rembrandt.c
@@ -22,6 +22,8 @@
#include <linux/pci.h>
#include <linux/pm_runtime.h>
+#include <asm/amd/node.h>
+
#include "amd.h"
#include "../mach-config.h"
#include "acp-mach.h"
@@ -31,47 +33,6 @@
#define MP1_C2PMSG_69 0x3B10A14
#define MP1_C2PMSG_85 0x3B10A54
#define MP1_C2PMSG_93 0x3B10A74
-#define HOST_BRIDGE_ID 0x14B5
-
-static struct acp_resource rsrc = {
- .offset = 0,
- .no_of_ctrls = 2,
- .irqp_used = 1,
- .soc_mclk = true,
- .irq_reg_offset = 0x1a00,
- .scratch_reg_offset = 0x12800,
- .sram_pte_offset = 0x03802800,
-};
-
-static struct snd_soc_acpi_codecs amp_rt1019 = {
- .num_codecs = 1,
- .codecs = {"10EC1019"}
-};
-
-static struct snd_soc_acpi_codecs amp_max = {
- .num_codecs = 1,
- .codecs = {"MX98360A"}
-};
-
-static struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = {
- {
- .id = "10508825",
- .drv_name = "rmb-nau8825-max",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &amp_max,
- },
- {
- .id = "AMDI0007",
- .drv_name = "rembrandt-acp",
- },
- {
- .id = "RTL5682",
- .drv_name = "rmb-rt5682s-rt1019",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &amp_rt1019,
- },
- {},
-};
static struct snd_soc_dai_driver acp_rmb_dai[] = {
{
@@ -166,29 +127,26 @@ static struct snd_soc_dai_driver acp_rmb_dai[] = {
static int acp6x_master_clock_generate(struct device *dev)
{
- int data = 0;
- struct pci_dev *smn_dev;
-
- smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, HOST_BRIDGE_ID, NULL);
- if (!smn_dev) {
- dev_err(dev, "Failed to get host bridge device\n");
- return -ENODEV;
- }
-
- smn_write(smn_dev, MP1_C2PMSG_93, 0);
- smn_write(smn_dev, MP1_C2PMSG_85, 0xC4);
- smn_write(smn_dev, MP1_C2PMSG_69, 0x4);
- read_poll_timeout(smn_read, data, data, DELAY_US,
- ACP_TIMEOUT, false, smn_dev, MP1_C2PMSG_93);
- return 0;
+ int data, rc;
+
+ rc = amd_smn_write(0, MP1_C2PMSG_93, 0);
+ if (rc)
+ return rc;
+ rc = amd_smn_write(0, MP1_C2PMSG_85, 0xC4);
+ if (rc)
+ return rc;
+ rc = amd_smn_write(0, MP1_C2PMSG_69, 0x4);
+ if (rc)
+ return rc;
+
+ return read_poll_timeout(smn_read_register, data, data > 0, DELAY_US,
+ ACP_TIMEOUT, false, MP1_C2PMSG_93);
}
static int rembrandt_audio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct acp_chip_info *chip;
- struct acp_dev_data *adata;
- struct resource *res;
u32 ret;
chip = dev_get_platdata(&pdev->dev);
@@ -202,45 +160,20 @@ static int rembrandt_audio_probe(struct platform_device *pdev)
return -ENODEV;
}
- adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
- if (!adata)
- return -ENOMEM;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
- if (!res) {
- dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
- return -ENODEV;
- }
-
- adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!adata->acp_base)
- return -ENOMEM;
+ chip->dev = dev;
+ chip->dai_driver = acp_rmb_dai;
+ chip->num_dai = ARRAY_SIZE(acp_rmb_dai);
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq");
- if (!res) {
- dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
- return -ENODEV;
- }
-
- adata->i2s_irq = res->start;
- adata->dev = dev;
- adata->dai_driver = acp_rmb_dai;
- adata->num_dai = ARRAY_SIZE(acp_rmb_dai);
- adata->rsrc = &rsrc;
- adata->acp_rev = chip->acp_rev;
- adata->flag = chip->flag;
- adata->is_i2s_config = chip->is_i2s_config;
- adata->machines = snd_soc_acpi_amd_rmb_acp_machines;
- acp_machine_select(adata);
-
- dev_set_drvdata(dev, adata);
-
- if (chip->is_i2s_config && rsrc.soc_mclk) {
+ if (chip->is_i2s_config && chip->rsrc->soc_mclk) {
ret = acp6x_master_clock_generate(dev);
if (ret)
return ret;
}
- acp_enable_interrupts(adata);
+ ret = acp_hw_en_interrupts(chip);
+ if (ret) {
+ dev_err(dev, "ACP en-interrupts failed\n");
+ return ret;
+ }
acp_platform_register(dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(&pdev->dev);
@@ -253,44 +186,48 @@ static int rembrandt_audio_probe(struct platform_device *pdev)
static void rembrandt_audio_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_platdata(dev);
+ int ret;
+
+ ret = acp_hw_dis_interrupts(chip);
+ if (ret)
+ dev_err(dev, "ACP dis-interrupts failed\n");
- acp_disable_interrupts(adata);
acp_platform_unregister(dev);
pm_runtime_disable(&pdev->dev);
}
-static int __maybe_unused rmb_pcm_resume(struct device *dev)
+static int rmb_pcm_resume(struct device *dev)
{
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_drvdata(dev->parent);
struct acp_stream *stream;
struct snd_pcm_substream *substream;
snd_pcm_uframes_t buf_in_frames;
u64 buf_size;
- if (adata->is_i2s_config && adata->rsrc->soc_mclk)
+ if (chip->is_i2s_config && chip->rsrc->soc_mclk)
acp6x_master_clock_generate(dev);
- spin_lock(&adata->acp_lock);
- list_for_each_entry(stream, &adata->stream_list, list) {
+ spin_lock(&chip->acp_lock);
+ list_for_each_entry(stream, &chip->stream_list, list) {
substream = stream->substream;
if (substream && substream->runtime) {
buf_in_frames = (substream->runtime->buffer_size);
buf_size = frames_to_bytes(substream->runtime, buf_in_frames);
- config_pte_for_stream(adata, stream);
- config_acp_dma(adata, stream, buf_size);
+ config_pte_for_stream(chip, stream);
+ config_acp_dma(chip, stream, buf_size);
if (stream->dai_id)
- restore_acp_i2s_params(substream, adata, stream);
+ restore_acp_i2s_params(substream, chip, stream);
else
- restore_acp_pdm_params(substream, adata);
+ restore_acp_pdm_params(substream, chip);
}
}
- spin_unlock(&adata->acp_lock);
+ spin_unlock(&chip->acp_lock);
return 0;
}
static const struct dev_pm_ops rmb_dma_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(NULL, rmb_pcm_resume)
+ SYSTEM_SLEEP_PM_OPS(NULL, rmb_pcm_resume)
};
static struct platform_driver rembrandt_driver = {
@@ -298,7 +235,7 @@ static struct platform_driver rembrandt_driver = {
.remove = rembrandt_audio_remove,
.driver = {
.name = "acp_asoc_rembrandt",
- .pm = &rmb_dma_pm_ops,
+ .pm = pm_ptr(&rmb_dma_pm_ops),
},
};
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
index ca2b74283d8f..04f6d70b6a92 100644
--- a/sound/soc/amd/acp/acp-renoir.c
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -27,55 +27,6 @@
#define DRV_NAME "acp_asoc_renoir"
-static struct acp_resource rsrc = {
- .offset = 20,
- .no_of_ctrls = 1,
- .irqp_used = 0,
- .irq_reg_offset = 0x1800,
- .scratch_reg_offset = 0x12800,
- .sram_pte_offset = 0x02052800,
-};
-
-static struct snd_soc_acpi_codecs amp_rt1019 = {
- .num_codecs = 1,
- .codecs = {"10EC1019"}
-};
-
-static struct snd_soc_acpi_codecs amp_max = {
- .num_codecs = 1,
- .codecs = {"MX98360A"}
-};
-
-static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[] = {
- {
- .id = "10EC5682",
- .drv_name = "acp3xalc56821019",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &amp_rt1019,
- },
- {
- .id = "RTL5682",
- .drv_name = "acp3xalc5682sm98360",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &amp_max,
- },
- {
- .id = "RTL5682",
- .drv_name = "acp3xalc5682s1019",
- .machine_quirk = snd_soc_acpi_codec_list,
- .quirk_data = &amp_rt1019,
- },
- {
- .id = "AMDI1019",
- .drv_name = "renoir-acp",
- },
- {
- .id = "ESSX8336",
- .drv_name = "acp3x-es83xx",
- },
- {},
-};
-
static struct snd_soc_dai_driver acp_renoir_dai[] = {
{
.name = "acp-i2s-sp",
@@ -147,8 +98,6 @@ static int renoir_audio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct acp_chip_info *chip;
- struct acp_dev_data *adata;
- struct resource *res;
int ret;
chip = dev_get_platdata(&pdev->dev);
@@ -162,37 +111,16 @@ static int renoir_audio_probe(struct platform_device *pdev)
return -ENODEV;
}
- adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
- if (!adata)
- return -ENOMEM;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
- if (!res) {
- dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
- return -ENODEV;
- }
-
- adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!adata->acp_base)
- return -ENOMEM;
+ chip->dev = dev;
+ chip->dai_driver = acp_renoir_dai;
+ chip->num_dai = ARRAY_SIZE(acp_renoir_dai);
- ret = platform_get_irq_byname(pdev, "acp_dai_irq");
- if (ret < 0)
+ ret = acp_hw_en_interrupts(chip);
+ if (ret) {
+ dev_err(dev, "ACP en-interrupts failed\n");
return ret;
- adata->i2s_irq = ret;
-
- adata->dev = dev;
- adata->dai_driver = acp_renoir_dai;
- adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
- adata->rsrc = &rsrc;
- adata->acp_rev = chip->acp_rev;
- adata->flag = chip->flag;
-
- adata->machines = snd_soc_acpi_amd_acp_machines;
- acp_machine_select(adata);
+ }
- dev_set_drvdata(dev, adata);
- acp_enable_interrupts(adata);
acp_platform_register(dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
@@ -206,40 +134,44 @@ static int renoir_audio_probe(struct platform_device *pdev)
static void renoir_audio_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_platdata(dev);
+ int ret;
+
+ ret = acp_hw_dis_interrupts(chip);
+ if (ret)
+ dev_err(dev, "ACP dis-interrupts failed\n");
- acp_disable_interrupts(adata);
acp_platform_unregister(dev);
}
-static int __maybe_unused rn_pcm_resume(struct device *dev)
+static int rn_pcm_resume(struct device *dev)
{
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_drvdata(dev->parent);
struct acp_stream *stream;
struct snd_pcm_substream *substream;
snd_pcm_uframes_t buf_in_frames;
u64 buf_size;
- spin_lock(&adata->acp_lock);
- list_for_each_entry(stream, &adata->stream_list, list) {
+ spin_lock(&chip->acp_lock);
+ list_for_each_entry(stream, &chip->stream_list, list) {
substream = stream->substream;
if (substream && substream->runtime) {
buf_in_frames = (substream->runtime->buffer_size);
buf_size = frames_to_bytes(substream->runtime, buf_in_frames);
- config_pte_for_stream(adata, stream);
- config_acp_dma(adata, stream, buf_size);
+ config_pte_for_stream(chip, stream);
+ config_acp_dma(chip, stream, buf_size);
if (stream->dai_id)
- restore_acp_i2s_params(substream, adata, stream);
+ restore_acp_i2s_params(substream, chip, stream);
else
- restore_acp_pdm_params(substream, adata);
+ restore_acp_pdm_params(substream, chip);
}
}
- spin_unlock(&adata->acp_lock);
+ spin_unlock(&chip->acp_lock);
return 0;
}
static const struct dev_pm_ops rn_dma_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(NULL, rn_pcm_resume)
+ SYSTEM_SLEEP_PM_OPS(NULL, rn_pcm_resume)
};
static struct platform_driver renoir_driver = {
@@ -247,7 +179,7 @@ static struct platform_driver renoir_driver = {
.remove = renoir_audio_remove,
.driver = {
.name = "acp_asoc_renoir",
- .pm = &rn_dma_pm_ops,
+ .pm = pm_ptr(&rn_dma_pm_ops),
},
};
diff --git a/sound/soc/amd/acp/acp-sdw-legacy-mach.c b/sound/soc/amd/acp/acp-sdw-legacy-mach.c
index 9280cd30d19c..6c24f9d8694e 100644
--- a/sound/soc/amd/acp/acp-sdw-legacy-mach.c
+++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c
@@ -28,6 +28,8 @@ static void log_quirks(struct device *dev)
SOC_JACK_JDSRC(soc_sdw_quirk));
if (soc_sdw_quirk & ASOC_SDW_ACP_DMIC)
dev_dbg(dev, "quirk SOC_SDW_ACP_DMIC enabled\n");
+ if (soc_sdw_quirk & ASOC_SDW_CODEC_SPKR)
+ dev_dbg(dev, "quirk ASOC_SDW_CODEC_SPKR enabled\n");
}
static int soc_sdw_quirk_cb(const struct dmi_system_id *id)
@@ -45,6 +47,38 @@ static const struct dmi_system_id soc_sdw_quirk_table[] = {
},
.driver_data = (void *)RT711_JD2,
},
+ {
+ .callback = soc_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D80"),
+ },
+ .driver_data = (void *)(ASOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = soc_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D81"),
+ },
+ .driver_data = (void *)(ASOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = soc_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D82"),
+ },
+ .driver_data = (void *)(ASOC_SDW_CODEC_SPKR),
+ },
+ {
+ .callback = soc_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0D83"),
+ },
+ .driver_data = (void *)(ASOC_SDW_CODEC_SPKR),
+ },
{}
};
@@ -122,6 +156,13 @@ static int create_sdw_dailink(struct snd_soc_card *card,
if (ret)
return ret;
break;
+ case ACP70_PCI_REV:
+ case ACP71_PCI_REV:
+ ret = get_acp70_cpu_pin_id(ffs(soc_end->link_mask - 1),
+ *be_id, &cpu_pin_id, dev);
+ if (ret)
+ return ret;
+ break;
default:
return -EINVAL;
}
@@ -221,6 +262,8 @@ static int create_sdw_dailinks(struct snd_soc_card *card,
switch (amd_ctx->acp_rev) {
case ACP63_PCI_REV:
+ case ACP70_PCI_REV:
+ case ACP71_PCI_REV:
sdw_platform_component->name = "amd_ps_sdw_dma.0";
break;
default:
@@ -229,7 +272,7 @@ static int create_sdw_dailinks(struct snd_soc_card *card,
/* generate DAI links by each sdw link */
while (soc_dais->initialised) {
- int current_be_id;
+ int current_be_id = 0;
ret = create_sdw_dailink(card, soc_dais, dai_links,
&current_be_id, codec_conf, sdw_platform_component);
@@ -266,6 +309,8 @@ static int create_dmic_dailinks(struct snd_soc_card *card,
switch (amd_ctx->acp_rev) {
case ACP63_PCI_REV:
+ case ACP70_PCI_REV:
+ case ACP71_PCI_REV:
pdm_cpu->name = "acp_ps_pdm_dma.0";
pdm_platform->name = "acp_ps_pdm_dma.0";
break;
@@ -276,7 +321,7 @@ static int create_dmic_dailinks(struct snd_soc_card *card,
*be_id = ACP_DMIC_BE_ID;
ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "acp-dmic-codec",
0, 1, // DMIC only supports capture
- pdm_cpu->name, pdm_platform->name, 1,
+ pdm_cpu->name, pdm_platform->name,
"dmic-codec.0", "dmic-hifi", no_pcm,
asoc_sdw_dmic_init, NULL);
if (ret)
diff --git a/sound/soc/amd/acp/acp-sdw-mach-common.c b/sound/soc/amd/acp/acp-sdw-mach-common.c
index 6f5c39ed1a18..e5f394dc2f4c 100644
--- a/sound/soc/amd/acp/acp-sdw-mach-common.c
+++ b/sound/soc/amd/acp/acp-sdw-mach-common.c
@@ -59,6 +59,40 @@ int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct dev
}
EXPORT_SYMBOL_NS_GPL(get_acp63_cpu_pin_id, "SND_SOC_AMD_SDW_MACH");
+int get_acp70_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev)
+{
+ switch (sdw_link_id) {
+ case AMD_SDW0:
+ case AMD_SDW1:
+ switch (be_id) {
+ case SOC_SDW_JACK_OUT_DAI_ID:
+ *cpu_pin_id = ACP70_SW_AUDIO0_TX;
+ break;
+ case SOC_SDW_JACK_IN_DAI_ID:
+ *cpu_pin_id = ACP70_SW_AUDIO0_RX;
+ break;
+ case SOC_SDW_AMP_OUT_DAI_ID:
+ *cpu_pin_id = ACP70_SW_AUDIO1_TX;
+ break;
+ case SOC_SDW_AMP_IN_DAI_ID:
+ *cpu_pin_id = ACP70_SW_AUDIO1_RX;
+ break;
+ case SOC_SDW_DMIC_DAI_ID:
+ *cpu_pin_id = ACP70_SW_AUDIO2_RX;
+ break;
+ default:
+ dev_err(dev, "Invalid be id:%d\n", be_id);
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ dev_dbg(dev, "sdw_link_id:%d, be_id:%d, cpu_pin_id:%d\n", sdw_link_id, be_id, *cpu_pin_id);
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(get_acp70_cpu_pin_id, "SND_SOC_AMD_SDW_MACH");
+
MODULE_DESCRIPTION("AMD SoundWire Common Machine driver");
MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c
index c09b1f118a6c..654fe78b2e2e 100644
--- a/sound/soc/amd/acp/acp-sdw-sof-mach.c
+++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c
@@ -128,6 +128,13 @@ static int create_sdw_dailink(struct snd_soc_card *card,
if (ret)
return ret;
break;
+ case ACP70_PCI_REV:
+ case ACP71_PCI_REV:
+ ret = get_acp70_cpu_pin_id(ffs(sof_end->link_mask - 1),
+ *be_id, &cpu_pin_id, dev);
+ if (ret)
+ return ret;
+ break;
default:
return -EINVAL;
}
@@ -219,7 +226,7 @@ static int create_sdw_dailinks(struct snd_soc_card *card,
/* generate DAI links by each sdw link */
while (sof_dais->initialised) {
- int current_be_id;
+ int current_be_id = 0;
ret = create_sdw_dailink(card, sof_dais, dai_links,
&current_be_id, codec_conf);
@@ -245,7 +252,6 @@ static int create_dmic_dailinks(struct snd_soc_card *card,
ret = asoc_sdw_init_simple_dai_link(dev, *dai_links, be_id, "acp-dmic-codec",
0, 1, // DMIC only supports capture
"acp-sof-dmic", platform_component->name,
- ARRAY_SIZE(platform_component),
"dmic-codec", "dmic-hifi", no_pcm,
asoc_sdw_dmic_init, NULL);
if (ret)
diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c
index d7b54f12f406..6215e31ecedd 100644
--- a/sound/soc/amd/acp/acp-sof-mach.c
+++ b/sound/soc/amd/acp/acp-sof-mach.c
@@ -88,7 +88,7 @@ static struct acp_card_drvdata sof_nau8821_max98388_data = {
static int acp_sof_probe(struct platform_device *pdev)
{
- struct snd_soc_card *card = NULL;
+ struct snd_soc_card *card;
struct device *dev = &pdev->dev;
struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev);
const struct dmi_system_id *dmi_id;
diff --git a/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c b/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c
index 2b0aa270a3e9..eb5d4a5baef2 100644
--- a/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c
+++ b/sound/soc/amd/acp/acp3x-es83xx/acp3x-es83xx.c
@@ -19,6 +19,7 @@
#include <linux/io.h>
#include <linux/acpi.h>
#include <linux/dmi.h>
+#include <linux/string_choices.h>
#include "../acp-mach.h"
#include "acp3x-es83xx.h"
@@ -241,9 +242,9 @@ static int acp3x_es83xx_configure_gpios(struct acp3x_es83xx_private *priv)
dev_info(priv->codec_dev, "speaker gpio %d active %s, headphone gpio %d active %s\n",
priv->enable_spk_gpio.crs_entry_index,
- priv->enable_spk_gpio.active_low ? "low" : "high",
+ str_low_high(priv->enable_spk_gpio.active_low),
priv->enable_hp_gpio.crs_entry_index,
- priv->enable_hp_gpio.active_low ? "low" : "high");
+ str_low_high(priv->enable_hp_gpio.active_low));
return 0;
}
diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c
index 81496e713440..10fb416b959d 100644
--- a/sound/soc/amd/acp/acp63.c
+++ b/sound/soc/amd/acp/acp63.c
@@ -20,6 +20,9 @@
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/pci.h>
+
+#include <asm/amd/node.h>
+
#include "amd.h"
#include "acp-mach.h"
#include "../mach-config.h"
@@ -49,24 +52,6 @@ union clk_pll_req_no {
u32 clk_pll_req_no_reg;
};
-static struct acp_resource rsrc = {
- .offset = 0,
- .no_of_ctrls = 2,
- .irqp_used = 1,
- .soc_mclk = true,
- .irq_reg_offset = 0x1a00,
- .scratch_reg_offset = 0x12800,
- .sram_pte_offset = 0x03802800,
-};
-
-static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines[] = {
- {
- .id = "AMDI0052",
- .drv_name = "acp63-acp",
- },
- {},
-};
-
static struct snd_soc_dai_driver acp63_dai[] = {
{
.name = "acp-i2s-sp",
@@ -158,47 +143,61 @@ static struct snd_soc_dai_driver acp63_dai[] = {
},
};
-static int acp63_i2s_master_clock_generate(struct acp_dev_data *adata)
+static int acp63_i2s_master_clock_generate(struct acp_chip_info *chip)
{
+ int rc;
u32 data;
union clk_pll_req_no clk_pll;
- struct pci_dev *smn_dev;
-
- smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x14E8, NULL);
- if (!smn_dev)
- return -ENODEV;
/* Clk5 pll register values to get mclk as 196.6MHz*/
clk_pll.bits.fb_mult_int = 0x31;
clk_pll.bits.pll_spine_div = 0;
clk_pll.bits.gb_mult_frac = 0x26E9;
- data = smn_read(smn_dev, CLK_PLL_PWR_REQ_N0);
- smn_write(smn_dev, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_STOP_REQ);
-
- data = smn_read(smn_dev, CLK_SPLL_FIELD_2_N0);
- if (data & PLL_FRANCE_EN)
- smn_write(smn_dev, CLK_SPLL_FIELD_2_N0, data | PLL_FRANCE_EN);
-
- smn_write(smn_dev, CLK_PLL_REQ_N0, clk_pll.clk_pll_req_no_reg);
-
- data = smn_read(smn_dev, CLK_PLL_PWR_REQ_N0);
- smn_write(smn_dev, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_START_REQ);
-
- data = smn_read(smn_dev, CLK_DFSBYPASS_CONTR);
- smn_write(smn_dev, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_0);
- smn_write(smn_dev, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_1);
+ rc = amd_smn_read(0, CLK_PLL_PWR_REQ_N0, &data);
+ if (rc)
+ return rc;
+ rc = amd_smn_write(0, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_STOP_REQ);
+ if (rc)
+ return rc;
+
+ rc = amd_smn_read(0, CLK_SPLL_FIELD_2_N0, &data);
+ if (rc)
+ return rc;
+ if (data & PLL_FRANCE_EN) {
+ rc = amd_smn_write(0, CLK_SPLL_FIELD_2_N0, data | PLL_FRANCE_EN);
+ if (rc)
+ return rc;
+ }
- smn_write(smn_dev, CLK_DFS_CNTL_N0, CLK0_DIVIDER);
- return 0;
+ rc = amd_smn_write(0, CLK_PLL_REQ_N0, clk_pll.clk_pll_req_no_reg);
+ if (rc)
+ return rc;
+
+ rc = amd_smn_read(0, CLK_PLL_PWR_REQ_N0, &data);
+ if (rc)
+ return rc;
+ rc = amd_smn_write(0, CLK_PLL_PWR_REQ_N0, data | PLL_AUTO_START_REQ);
+ if (rc)
+ return rc;
+
+ rc = amd_smn_read(0, CLK_DFSBYPASS_CONTR, &data);
+ if (rc)
+ return rc;
+ rc = amd_smn_write(0, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_0);
+ if (rc)
+ return rc;
+ rc = amd_smn_write(0, CLK_DFSBYPASS_CONTR, data | EXIT_DPF_BYPASS_1);
+ if (rc)
+ return rc;
+
+ return amd_smn_write(0, CLK_DFS_CNTL_N0, CLK0_DIVIDER);
}
static int acp63_audio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct acp_chip_info *chip;
- struct acp_dev_data *adata;
- struct resource *res;
int ret;
chip = dev_get_platdata(&pdev->dev);
@@ -212,44 +211,20 @@ static int acp63_audio_probe(struct platform_device *pdev)
return -ENODEV;
}
- adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
- if (!adata)
- return -ENOMEM;
+ chip->dev = dev;
+ chip->dai_driver = acp63_dai;
+ chip->num_dai = ARRAY_SIZE(acp63_dai);
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
- if (!res) {
- dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
- return -ENODEV;
- }
-
- adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!adata->acp_base)
- return -ENOMEM;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq");
- if (!res) {
- dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
- return -ENODEV;
- }
-
- adata->i2s_irq = res->start;
- adata->dev = dev;
- adata->dai_driver = acp63_dai;
- adata->num_dai = ARRAY_SIZE(acp63_dai);
- adata->rsrc = &rsrc;
- adata->acp_rev = chip->acp_rev;
- adata->flag = chip->flag;
- adata->is_i2s_config = chip->is_i2s_config;
- adata->machines = snd_soc_acpi_amd_acp63_acp_machines;
- acp_machine_select(adata);
- dev_set_drvdata(dev, adata);
-
- if (chip->is_i2s_config && rsrc.soc_mclk) {
- ret = acp63_i2s_master_clock_generate(adata);
+ if (chip->is_i2s_config && chip->rsrc->soc_mclk) {
+ ret = acp63_i2s_master_clock_generate(chip);
if (ret)
return ret;
}
- acp_enable_interrupts(adata);
+ ret = acp_hw_en_interrupts(chip);
+ if (ret) {
+ dev_err(dev, "ACP en-interrupts failed\n");
+ return ret;
+ }
acp_platform_register(dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(&pdev->dev);
@@ -262,44 +237,48 @@ static int acp63_audio_probe(struct platform_device *pdev)
static void acp63_audio_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_platdata(dev);
+ int ret;
+
+ ret = acp_hw_dis_interrupts(chip);
+ if (ret)
+ dev_err(dev, "ACP dis-interrupts failed\n");
- acp_disable_interrupts(adata);
acp_platform_unregister(dev);
pm_runtime_disable(&pdev->dev);
}
-static int __maybe_unused acp63_pcm_resume(struct device *dev)
+static int acp63_pcm_resume(struct device *dev)
{
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_drvdata(dev->parent);
struct acp_stream *stream;
struct snd_pcm_substream *substream;
snd_pcm_uframes_t buf_in_frames;
u64 buf_size;
- if (adata->is_i2s_config && adata->rsrc->soc_mclk)
- acp63_i2s_master_clock_generate(adata);
+ if (chip->is_i2s_config && chip->rsrc->soc_mclk)
+ acp63_i2s_master_clock_generate(chip);
- spin_lock(&adata->acp_lock);
- list_for_each_entry(stream, &adata->stream_list, list) {
+ spin_lock(&chip->acp_lock);
+ list_for_each_entry(stream, &chip->stream_list, list) {
substream = stream->substream;
if (substream && substream->runtime) {
buf_in_frames = (substream->runtime->buffer_size);
buf_size = frames_to_bytes(substream->runtime, buf_in_frames);
- config_pte_for_stream(adata, stream);
- config_acp_dma(adata, stream, buf_size);
+ config_pte_for_stream(chip, stream);
+ config_acp_dma(chip, stream, buf_size);
if (stream->dai_id)
- restore_acp_i2s_params(substream, adata, stream);
+ restore_acp_i2s_params(substream, chip, stream);
else
- restore_acp_pdm_params(substream, adata);
+ restore_acp_pdm_params(substream, chip);
}
}
- spin_unlock(&adata->acp_lock);
+ spin_unlock(&chip->acp_lock);
return 0;
}
static const struct dev_pm_ops acp63_dma_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(NULL, acp63_pcm_resume)
+ SYSTEM_SLEEP_PM_OPS(NULL, acp63_pcm_resume)
};
static struct platform_driver acp63_driver = {
@@ -307,7 +286,7 @@ static struct platform_driver acp63_driver = {
.remove = acp63_audio_remove,
.driver = {
.name = "acp_asoc_acp63",
- .pm = &acp63_dma_pm_ops,
+ .pm = pm_ptr(&acp63_dma_pm_ops),
},
};
diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c
index 9e23729fd1a7..b95e3949e70b 100644
--- a/sound/soc/amd/acp/acp70.c
+++ b/sound/soc/amd/acp/acp70.c
@@ -23,29 +23,13 @@
#include "amd.h"
#include "acp-mach.h"
+#include <asm/amd/node.h>
+
#define DRV_NAME "acp_asoc_acp70"
#define CLK7_CLK0_DFS_CNTL_N1 0X0006C1A4
#define CLK0_DIVIDER 0X19
-static struct acp_resource rsrc = {
- .offset = 0,
- .no_of_ctrls = 2,
- .irqp_used = 1,
- .soc_mclk = true,
- .irq_reg_offset = 0x1a00,
- .scratch_reg_offset = 0x10000,
- .sram_pte_offset = 0x03800000,
-};
-
-static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[] = {
- {
- .id = "AMDI0029",
- .drv_name = "acp70-acp",
- },
- {},
-};
-
static struct snd_soc_dai_driver acp70_dai[] = {
{
.name = "acp-i2s-sp",
@@ -137,35 +121,10 @@ static struct snd_soc_dai_driver acp70_dai[] = {
},
};
-static int acp70_i2s_master_clock_generate(struct acp_dev_data *adata)
-{
- struct pci_dev *smn_dev;
- u32 device_id;
-
- if (adata->acp_rev == ACP70_PCI_ID)
- device_id = 0x1507;
- else if (adata->acp_rev == ACP71_PCI_ID)
- device_id = 0x1122;
- else
- return -ENODEV;
-
- smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, device_id, NULL);
-
- if (!smn_dev)
- return -ENODEV;
-
- /* Set clk7 DFS clock divider register value to get mclk as 196.608MHz*/
- smn_write(smn_dev, CLK7_CLK0_DFS_CNTL_N1, CLK0_DIVIDER);
-
- return 0;
-}
-
static int acp_acp70_audio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct acp_chip_info *chip;
- struct acp_dev_data *adata;
- struct resource *res;
int ret;
chip = dev_get_platdata(&pdev->dev);
@@ -183,44 +142,21 @@ static int acp_acp70_audio_probe(struct platform_device *pdev)
return -ENODEV;
}
- adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
- if (!adata)
- return -ENOMEM;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
- if (!res) {
- dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
- return -ENODEV;
- }
-
- adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!adata->acp_base)
- return -ENOMEM;
-
- res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq");
- if (!res) {
- dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
- return -ENODEV;
- }
-
- adata->i2s_irq = res->start;
- adata->dev = dev;
- adata->dai_driver = acp70_dai;
- adata->num_dai = ARRAY_SIZE(acp70_dai);
- adata->rsrc = &rsrc;
- adata->machines = snd_soc_acpi_amd_acp70_acp_machines;
- adata->acp_rev = chip->acp_rev;
- adata->flag = chip->flag;
- acp_machine_select(adata);
-
- dev_set_drvdata(dev, adata);
+ chip->dev = dev;
+ chip->dai_driver = acp70_dai;
+ chip->num_dai = ARRAY_SIZE(acp70_dai);
- ret = acp70_i2s_master_clock_generate(adata);
+ /* Set clk7 DFS clock divider register value to get mclk as 196.608MHz*/
+ ret = amd_smn_write(0, CLK7_CLK0_DFS_CNTL_N1, CLK0_DIVIDER);
if (ret) {
dev_err(&pdev->dev, "Failed to set I2S master clock as 196.608MHz\n");
return ret;
}
- acp_enable_interrupts(adata);
+ ret = acp_hw_en_interrupts(chip);
+ if (ret) {
+ dev_err(dev, "ACP en-interrupts failed\n");
+ return ret;
+ }
acp_platform_register(dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(&pdev->dev);
@@ -233,43 +169,45 @@ static int acp_acp70_audio_probe(struct platform_device *pdev)
static void acp_acp70_audio_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_platdata(dev);
+ int ret;
+
+ ret = acp_hw_dis_interrupts(chip);
+ if (ret)
+ dev_err(dev, "ACP dis-interrupts failed\n");
- acp_disable_interrupts(adata);
acp_platform_unregister(dev);
pm_runtime_disable(&pdev->dev);
}
-static int __maybe_unused acp70_pcm_resume(struct device *dev)
+static int acp70_pcm_resume(struct device *dev)
{
- struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_chip_info *chip = dev_get_drvdata(dev->parent);
struct acp_stream *stream;
struct snd_pcm_substream *substream;
snd_pcm_uframes_t buf_in_frames;
u64 buf_size;
- spin_lock(&adata->acp_lock);
- list_for_each_entry(stream, &adata->stream_list, list) {
- if (stream) {
- substream = stream->substream;
- if (substream && substream->runtime) {
- buf_in_frames = (substream->runtime->buffer_size);
- buf_size = frames_to_bytes(substream->runtime, buf_in_frames);
- config_pte_for_stream(adata, stream);
- config_acp_dma(adata, stream, buf_size);
- if (stream->dai_id)
- restore_acp_i2s_params(substream, adata, stream);
- else
- restore_acp_pdm_params(substream, adata);
- }
+ spin_lock(&chip->acp_lock);
+ list_for_each_entry(stream, &chip->stream_list, list) {
+ substream = stream->substream;
+ if (substream && substream->runtime) {
+ buf_in_frames = (substream->runtime->buffer_size);
+ buf_size = frames_to_bytes(substream->runtime, buf_in_frames);
+ config_pte_for_stream(chip, stream);
+ config_acp_dma(chip, stream, buf_size);
+ if (stream->dai_id)
+ restore_acp_i2s_params(substream, chip, stream);
+ else
+ restore_acp_pdm_params(substream, chip);
}
}
- spin_unlock(&adata->acp_lock);
+ spin_unlock(&chip->acp_lock);
return 0;
}
static const struct dev_pm_ops acp70_dma_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(NULL, acp70_pcm_resume)
+ SYSTEM_SLEEP_PM_OPS(NULL, acp70_pcm_resume)
};
static struct platform_driver acp70_driver = {
@@ -277,7 +215,7 @@ static struct platform_driver acp70_driver = {
.remove = acp_acp70_audio_remove,
.driver = {
.name = "acp_asoc_acp70",
- .pm = &acp70_dma_pm_ops,
+ .pm = pm_ptr(&acp70_dma_pm_ops),
},
};
diff --git a/sound/soc/amd/acp/amd-acp70-acpi-match.c b/sound/soc/amd/acp/amd-acp70-acpi-match.c
new file mode 100644
index 000000000000..e87ccfeee5bd
--- /dev/null
+++ b/sound/soc/amd/acp/amd-acp70-acpi-match.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * amd-acp70-acpi-match.c - tables and support for ACP 7.0 & ACP7.1
+ * ACPI enumeration.
+ *
+ * Copyright 2025 Advanced Micro Devices, Inc.
+ */
+
+#include <sound/soc-acpi.h>
+#include "../mach-config.h"
+
+static const struct snd_soc_acpi_endpoint single_endpoint = {
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0
+};
+
+static const struct snd_soc_acpi_endpoint spk_l_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 0,
+ .group_id = 1
+};
+
+static const struct snd_soc_acpi_endpoint spk_r_endpoint = {
+ .num = 0,
+ .aggregated = 1,
+ .group_position = 1,
+ .group_id = 1
+};
+
+static const struct snd_soc_acpi_adr_device rt711_rt1316_group_adr[] = {
+ {
+ .adr = 0x000030025D071101ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt711"
+ },
+ {
+ .adr = 0x000030025D131601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_l_endpoint,
+ .name_prefix = "rt1316-1"
+ },
+ {
+ .adr = 0x000032025D131601ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "rt1316-2"
+ },
+};
+
+static const struct snd_soc_acpi_adr_device rt714_adr[] = {
+ {
+ .adr = 0x130025d071401ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt714"
+ }
+};
+
+static const struct snd_soc_acpi_link_adr acp70_4_in_1_sdca[] = {
+ { .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt711_rt1316_group_adr),
+ .adr_d = rt711_rt1316_group_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt714_adr),
+ .adr_d = rt714_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_endpoint rt722_endpoints[] = {
+ {
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ {
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ {
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
+static const struct snd_soc_acpi_adr_device rt722_0_single_adr[] = {
+ {
+ .adr = 0x000030025d072201ull,
+ .num_endpoints = ARRAY_SIZE(rt722_endpoints),
+ .endpoints = rt722_endpoints,
+ .name_prefix = "rt722"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device rt1320_1_single_adr[] = {
+ {
+ .adr = 0x000130025D132001ull,
+ .num_endpoints = 1,
+ .endpoints = &single_endpoint,
+ .name_prefix = "rt1320-1"
+ }
+};
+
+static const struct snd_soc_acpi_link_adr acp70_rt722_only[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt722_0_single_adr),
+ .adr_d = rt722_0_single_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_link_adr acp70_rt722_l0_rt1320_l1[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt722_0_single_adr),
+ .adr_d = rt722_0_single_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt1320_1_single_adr),
+ .adr_d = rt1320_1_single_adr,
+ },
+ {}
+};
+
+struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sdw_machines[] = {
+ {
+ .link_mask = BIT(0) | BIT(1),
+ .links = acp70_rt722_l0_rt1320_l1,
+ .drv_name = "amd_sdw",
+ },
+ {
+ .link_mask = BIT(0),
+ .links = acp70_rt722_only,
+ .drv_name = "amd_sdw",
+ },
+ {
+ .link_mask = BIT(0) | BIT(1),
+ .links = acp70_4_in_1_sdca,
+ .drv_name = "amd_sdw",
+ },
+ {},
+};
+EXPORT_SYMBOL(snd_soc_acpi_amd_acp70_sdw_machines);
+
+MODULE_DESCRIPTION("AMD ACP7.0 & ACP7.1 tables and support for ACPI enumeration");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
diff --git a/sound/soc/amd/acp/amd-acpi-mach.c b/sound/soc/amd/acp/amd-acpi-mach.c
new file mode 100644
index 000000000000..d95047d2ee94
--- /dev/null
+++ b/sound/soc/amd/acp/amd-acpi-mach.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * amd-acpi-match.c - tables and support for ACP platforms
+ * ACPI enumeration.
+ *
+ * Copyright 2025 Advanced Micro Devices, Inc.
+ */
+
+#include <sound/soc-acpi.h>
+
+struct snd_soc_acpi_codecs amp_rt1019 = {
+ .num_codecs = 1,
+ .codecs = {"10EC1019"}
+};
+
+struct snd_soc_acpi_codecs amp_max = {
+ .num_codecs = 1,
+ .codecs = {"MX98360A"}
+};
+
+struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines[] = {
+ {
+ .id = "10EC5682",
+ .drv_name = "acp3xalc56821019",
+ .machine_quirk = snd_soc_acpi_codec_list,
+ .quirk_data = &amp_rt1019,
+ },
+ {
+ .id = "RTL5682",
+ .drv_name = "acp3xalc5682sm98360",
+ .machine_quirk = snd_soc_acpi_codec_list,
+ .quirk_data = &amp_max,
+ },
+ {
+ .id = "RTL5682",
+ .drv_name = "acp3xalc5682s1019",
+ .machine_quirk = snd_soc_acpi_codec_list,
+ .quirk_data = &amp_rt1019,
+ },
+ {
+ .id = "AMDI1019",
+ .drv_name = "renoir-acp",
+ },
+ {
+ .id = "ESSX8336",
+ .drv_name = "acp3x-es83xx",
+ },
+ {},
+};
+EXPORT_SYMBOL_NS_GPL(snd_soc_acpi_amd_acp_machines, "SND_SOC_ACP_COMMON");
+
+struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = {
+ {
+ .id = "10508825",
+ .drv_name = "rmb-nau8825-max",
+ .machine_quirk = snd_soc_acpi_codec_list,
+ .quirk_data = &amp_max,
+ },
+ {
+ .id = "AMDI0007",
+ .drv_name = "rembrandt-acp",
+ },
+ {
+ .id = "RTL5682",
+ .drv_name = "rmb-rt5682s-rt1019",
+ .machine_quirk = snd_soc_acpi_codec_list,
+ .quirk_data = &amp_rt1019,
+ },
+ {},
+};
+EXPORT_SYMBOL_NS_GPL(snd_soc_acpi_amd_rmb_acp_machines, "SND_SOC_ACP_COMMON");
+
+struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines[] = {
+ {
+ .id = "AMDI0052",
+ .drv_name = "acp63-acp",
+ },
+ {},
+};
+EXPORT_SYMBOL_NS_GPL(snd_soc_acpi_amd_acp63_acp_machines, "SND_SOC_ACP_COMMON");
+
+struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[] = {
+ {
+ .id = "AMDI0029",
+ .drv_name = "acp70-acp",
+ },
+ {},
+};
+EXPORT_SYMBOL_NS_GPL(snd_soc_acpi_amd_acp70_acp_machines, "SND_SOC_ACP_COMMON");
+
+MODULE_DESCRIPTION("AMD ACP tables and support for ACPI enumeration");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Venkataprasad.potturu@amd.com");
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index ee69dfb10cb8..863e74fcee43 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -140,13 +140,36 @@
struct acp_chip_info {
char *name; /* Platform name */
+ struct resource *res;
+ struct device *dev;
+ struct snd_soc_dai_driver *dai_driver;
+
unsigned int acp_rev; /* ACP Revision id */
void __iomem *base; /* ACP memory PCI base */
+ struct snd_acp_hw_ops *acp_hw_ops;
+ int (*acp_hw_ops_init)(struct acp_chip_info *chip);
struct platform_device *chip_pdev;
+ struct acp_resource *rsrc; /* Platform specific resources*/
+ struct list_head stream_list;
+ spinlock_t acp_lock; /* Used to protect stream_list */
+ struct platform_device *dmic_codec_dev;
+ struct platform_device *acp_plat_dev;
+ struct platform_device *mach_dev;
+ struct snd_soc_acpi_mach *machines;
+ int num_dai;
+ u32 addr;
+ u32 bclk_div;
+ u32 lrclk_div;
+ u32 ch_mask;
+ u32 tdm_tx_fmt[3];
+ u32 tdm_rx_fmt[3];
+ u32 xfer_tx_resolution[3];
+ u32 xfer_rx_resolution[3];
unsigned int flag; /* Distinguish b/w Legacy or Only PDM */
bool is_pdm_dev; /* flag set to true when ACP PDM controller exists */
bool is_pdm_config; /* flag set to true when PDM configuration is selected from BIOS */
bool is_i2s_config; /* flag set to true when I2S configuration is selected from BIOS */
+ bool tdm_mode;
};
struct acp_stream {
@@ -172,35 +195,23 @@ struct acp_resource {
u64 sram_pte_offset;
};
-struct acp_dev_data {
- char *name;
- struct device *dev;
- void __iomem *acp_base;
- unsigned int i2s_irq;
- unsigned int acp_rev; /* ACP Revision id */
-
- bool tdm_mode;
- bool is_i2s_config;
- /* SOC specific dais */
- struct snd_soc_dai_driver *dai_driver;
- int num_dai;
-
- struct list_head stream_list;
- spinlock_t acp_lock;
-
- struct snd_soc_acpi_mach *machines;
- struct platform_device *mach_dev;
-
- u32 bclk_div;
- u32 lrclk_div;
-
- struct acp_resource *rsrc;
- u32 ch_mask;
- u32 tdm_tx_fmt[3];
- u32 tdm_rx_fmt[3];
- u32 xfer_tx_resolution[3];
- u32 xfer_rx_resolution[3];
- unsigned int flag;
+/**
+ * struct snd_acp_hw_ops - ACP PCI driver platform specific ops
+ * @acp_init: ACP initialization
+ * @acp_deinit: ACP de-initialization
+ * @irq: ACP irq handler
+ * @en_interrupts: ACP enable interrupts
+ * @dis_interrupts: ACP disable interrupts
+ */
+struct snd_acp_hw_ops {
+ /* ACP hardware initilizations */
+ int (*acp_init)(struct acp_chip_info *chip);
+ int (*acp_deinit)(struct acp_chip_info *chip);
+
+ /* ACP Interrupts*/
+ irqreturn_t (*irq)(int irq, void *data);
+ int (*en_interrupts)(struct acp_chip_info *chip);
+ int (*dis_interrupts)(struct acp_chip_info *chip);
};
enum acp_config {
@@ -227,76 +238,121 @@ enum acp_config {
ACP_CONFIG_20,
};
+extern struct acp_resource rn_rsrc;
+extern struct acp_resource rmb_rsrc;
+extern struct acp_resource acp63_rsrc;
+extern struct acp_resource acp70_rsrc;
+
+extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp_machines;
+extern struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines;
+extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp63_acp_machines;
+extern struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines;
+
extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
extern const struct snd_soc_dai_ops acp_dmic_dai_ops;
int acp_platform_register(struct device *dev);
int acp_platform_unregister(struct device *dev);
-int acp_machine_select(struct acp_dev_data *adata);
-
-int smn_read(struct pci_dev *dev, u32 smn_addr);
-int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data);
+int acp_machine_select(struct acp_chip_info *chip);
int acp_init(struct acp_chip_info *chip);
int acp_deinit(struct acp_chip_info *chip);
-void acp_enable_interrupts(struct acp_dev_data *adata);
-void acp_disable_interrupts(struct acp_dev_data *adata);
+int acp_enable_interrupts(struct acp_chip_info *chip);
+int acp_disable_interrupts(struct acp_chip_info *chip);
+irqreturn_t acp_irq_handler(int irq, void *data);
+
+extern struct snd_acp_hw_ops acp31_common_hw_ops;
+extern struct snd_acp_hw_ops acp6x_common_hw_ops;
+extern struct snd_acp_hw_ops acp63_common_hw_ops;
+extern struct snd_acp_hw_ops acp70_common_hw_ops;
+extern int acp31_hw_ops_init(struct acp_chip_info *chip);
+extern int acp6x_hw_ops_init(struct acp_chip_info *chip);
+extern int acp63_hw_ops_init(struct acp_chip_info *chip);
+extern int acp70_hw_ops_init(struct acp_chip_info *chip);
/* Machine configuration */
int snd_amd_acp_find_config(struct pci_dev *pci);
-void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream);
-void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int size);
+void config_pte_for_stream(struct acp_chip_info *chip, struct acp_stream *stream);
+void config_acp_dma(struct acp_chip_info *chip, struct acp_stream *stream, int size);
void restore_acp_pdm_params(struct snd_pcm_substream *substream,
- struct acp_dev_data *adata);
+ struct acp_chip_info *chip);
int restore_acp_i2s_params(struct snd_pcm_substream *substream,
- struct acp_dev_data *adata, struct acp_stream *stream);
+ struct acp_chip_info *chip, struct acp_stream *stream);
void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip);
-static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
+static inline int acp_hw_init(struct acp_chip_info *chip)
+{
+ if (chip && chip->acp_hw_ops && chip->acp_hw_ops->acp_init)
+ return chip->acp_hw_ops->acp_init(chip);
+ return -EOPNOTSUPP;
+}
+
+static inline int acp_hw_deinit(struct acp_chip_info *chip)
+{
+ if (chip && chip->acp_hw_ops && chip->acp_hw_ops->acp_deinit)
+ return chip->acp_hw_ops->acp_deinit(chip);
+ return -EOPNOTSUPP;
+}
+
+static inline int acp_hw_en_interrupts(struct acp_chip_info *chip)
+{
+ if (chip && chip->acp_hw_ops && chip->acp_hw_ops->en_interrupts)
+ return chip->acp_hw_ops->en_interrupts(chip);
+ return -EOPNOTSUPP;
+}
+
+static inline int acp_hw_dis_interrupts(struct acp_chip_info *chip)
+{
+ if (chip && chip->acp_hw_ops && chip->acp_hw_ops->dis_interrupts)
+ chip->acp_hw_ops->dis_interrupts(chip);
+ return -EOPNOTSUPP;
+}
+
+static inline u64 acp_get_byte_count(struct acp_chip_info *chip, int dai_id, int direction)
{
u64 byte_count = 0, low = 0, high = 0;
if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
switch (dai_id) {
case I2S_BT_INSTANCE:
- high = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH(adata));
- low = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW(adata));
+ high = readl(chip->base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH(chip));
+ low = readl(chip->base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW(chip));
break;
case I2S_SP_INSTANCE:
- high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH(adata));
- low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW(adata));
+ high = readl(chip->base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH(chip));
+ low = readl(chip->base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW(chip));
break;
case I2S_HS_INSTANCE:
- high = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH);
- low = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_LOW);
+ high = readl(chip->base + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH);
+ low = readl(chip->base + ACP_HS_TX_LINEARPOSITIONCNTR_LOW);
break;
default:
- dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
+ dev_err(chip->dev, "Invalid dai id %x\n", dai_id);
goto POINTER_RETURN_BYTES;
}
} else {
switch (dai_id) {
case I2S_BT_INSTANCE:
- high = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH(adata));
- low = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW(adata));
+ high = readl(chip->base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH(chip));
+ low = readl(chip->base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW(chip));
break;
case I2S_SP_INSTANCE:
- high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH(adata));
- low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW(adata));
+ high = readl(chip->base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH(chip));
+ low = readl(chip->base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW(chip));
break;
case I2S_HS_INSTANCE:
- high = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH);
- low = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_LOW);
+ high = readl(chip->base + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH);
+ low = readl(chip->base + ACP_HS_RX_LINEARPOSITIONCNTR_LOW);
break;
case DMIC_INSTANCE:
- high = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH);
- low = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW);
+ high = readl(chip->base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH);
+ low = readl(chip->base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW);
break;
default:
- dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
+ dev_err(chip->dev, "Invalid dai id %x\n", dai_id);
goto POINTER_RETURN_BYTES;
}
}
diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h
index 117ea63e85c6..82275c9de53a 100644
--- a/sound/soc/amd/acp/chip_offset_byte.h
+++ b/sound/soc/amd/acp/chip_offset_byte.h
@@ -29,13 +29,13 @@
#define ACP_PIN_CONFIG 0x1440
#define ACP3X_PIN_CONFIG 0x1400
-#define ACP_EXTERNAL_INTR_REG_ADDR(adata, offset, ctrl) \
- (adata->acp_base + adata->rsrc->irq_reg_offset + offset + (ctrl * 0x04))
+#define ACP_EXTERNAL_INTR_REG_ADDR(chip, offset, ctrl) \
+ (chip->base + chip->rsrc->irq_reg_offset + offset + (ctrl * 0x04))
-#define ACP_EXTERNAL_INTR_ENB(adata) ACP_EXTERNAL_INTR_REG_ADDR(adata, 0x0, 0x0)
-#define ACP_EXTERNAL_INTR_CNTL(adata, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(adata, 0x4, ctrl)
-#define ACP_EXTERNAL_INTR_STAT(adata, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(adata, \
- (0x4 + (adata->rsrc->no_of_ctrls * 0x04)), ctrl)
+#define ACP_EXTERNAL_INTR_ENB(chip) ACP_EXTERNAL_INTR_REG_ADDR(chip, 0x0, 0x0)
+#define ACP_EXTERNAL_INTR_CNTL(chip, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(chip, 0x4, ctrl)
+#define ACP_EXTERNAL_INTR_STAT(chip, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(chip, \
+ (0x4 + (chip->rsrc->no_of_ctrls * 0x04)), ctrl)
/* Registers from ACP_AUDIO_BUFFERS block */
diff --git a/sound/soc/amd/acp/soc_amd_sdw_common.h b/sound/soc/amd/acp/soc_amd_sdw_common.h
index b7bae107c13e..1f24e0e06487 100644
--- a/sound/soc/amd/acp/soc_amd_sdw_common.h
+++ b/sound/soc/amd/acp/soc_amd_sdw_common.h
@@ -19,9 +19,12 @@
#define AMD_SDW_MAX_GROUPS 9
#define ACP63_PCI_REV 0x63
+#define ACP70_PCI_REV 0x70
+#define ACP71_PCI_REV 0x71
#define SOC_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0))
#define ASOC_SDW_FOUR_SPK BIT(4)
#define ASOC_SDW_ACP_DMIC BIT(5)
+#define ASOC_SDW_CODEC_SPKR BIT(15)
#define AMD_SDW0 0
#define AMD_SDW1 1
@@ -38,11 +41,20 @@
#define ACP_DMIC_BE_ID 4
+#define ACP70_SW_AUDIO0_TX 0
+#define ACP70_SW_AUDIO1_TX 1
+#define ACP70_SW_AUDIO2_TX 2
+
+#define ACP70_SW_AUDIO0_RX 3
+#define ACP70_SW_AUDIO1_RX 4
+#define ACP70_SW_AUDIO2_RX 5
+
struct amd_mc_ctx {
unsigned int acp_rev;
unsigned int max_sdw_links;
};
int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev);
+int get_acp70_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct device *dev);
#endif