{
struct device *dev = dai->component->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_resource *rsrc = adata->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;
case I2S_SP_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
reg_dma_size = ACP_I2S_TX_DMA_SIZE;
- acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+ acp_fifo_addr = rsrc->sram_pte_offset +
SP_PB_FIFO_ADDR_OFFSET;
reg_fifo_addr = ACP_I2S_TX_FIFOADDR;
reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
} else {
reg_dma_size = ACP_I2S_RX_DMA_SIZE;
- acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+ acp_fifo_addr = rsrc->sram_pte_offset +
SP_CAPT_FIFO_ADDR_OFFSET;
reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
case I2S_BT_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
reg_dma_size = ACP_BT_TX_DMA_SIZE;
- acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+ acp_fifo_addr = rsrc->sram_pte_offset +
BT_PB_FIFO_ADDR_OFFSET;
reg_fifo_addr = ACP_BT_TX_FIFOADDR;
reg_fifo_size = ACP_BT_TX_FIFOSIZE;
writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
} else {
reg_dma_size = ACP_BT_RX_DMA_SIZE;
- acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
+ acp_fifo_addr = rsrc->sram_pte_offset +
BT_CAPT_FIFO_ADDR_OFFSET;
reg_fifo_addr = ACP_BT_RX_FIFOADDR;
reg_fifo_size = ACP_BT_RX_FIFOSIZE;
writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
- ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
- ext_int_ctrl |= BIT(I2S_RX_THRESHOLD) | BIT(BT_RX_THRESHOLD)
- | BIT(I2S_TX_THRESHOLD) | BIT(BT_TX_THRESHOLD);
+ ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
+ ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
+ BIT(BT_RX_THRESHOLD(rsrc->offset)) |
+ BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
+ BIT(BT_TX_THRESHOLD(rsrc->offset));
- writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+ writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
return 0;
}
{
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;
unsigned int dir = substream->stream;
unsigned int irq_bit = 0;
switch (dai->driver->id) {
case I2S_SP_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
- irq_bit = BIT(I2S_TX_THRESHOLD);
+ irq_bit = BIT(I2S_TX_THRESHOLD(rsrc->offset));
stream->pte_offset = ACP_SRAM_SP_PB_PTE_OFFSET;
stream->fifo_offset = SP_PB_FIFO_ADDR_OFFSET;
} else {
- irq_bit = BIT(I2S_RX_THRESHOLD);
+ irq_bit = BIT(I2S_RX_THRESHOLD(rsrc->offset));
stream->pte_offset = ACP_SRAM_SP_CP_PTE_OFFSET;
stream->fifo_offset = SP_CAPT_FIFO_ADDR_OFFSET;
}
break;
case I2S_BT_INSTANCE:
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
- irq_bit = BIT(BT_TX_THRESHOLD);
+ irq_bit = BIT(BT_TX_THRESHOLD(rsrc->offset));
stream->pte_offset = ACP_SRAM_BT_PB_PTE_OFFSET;
stream->fifo_offset = BT_PB_FIFO_ADDR_OFFSET;
} else {
- irq_bit = BIT(BT_RX_THRESHOLD);
+ irq_bit = BIT(BT_RX_THRESHOLD(rsrc->offset));
stream->pte_offset = ACP_SRAM_BT_CP_PTE_OFFSET;
stream->fifo_offset = BT_CAPT_FIFO_ADDR_OFFSET;
}
{
struct device *dev = dai->component->dev;
struct acp_dev_data *adata = dev_get_drvdata(dev);
+ struct acp_resource *rsrc = adata->rsrc;
unsigned int val;
if (!adata->acp_base) {
return -EINVAL;
}
- val = readl(adata->acp_base + ACP_I2S_PIN_CONFIG);
- if (val != I2S_MODE) {
+ val = readl(adata->acp_base + rsrc->i2s_pin_cfg_offset);
+ if (val != rsrc->i2s_mode) {
dev_err(dev, "I2S Mode not supported val %x\n", val);
return -EINVAL;
}
stream->reg_offset = ACP_REGION2_OFFSET;
/* Enable DMIC Interrupts */
- ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+ ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
ext_int_ctrl |= PDM_DMA_INTR_MASK;
- writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+ writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
return 0;
}
u32 ext_int_ctrl;
/* Disable DMIC interrupts */
- ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+ ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
ext_int_ctrl |= ~PDM_DMA_INTR_MASK;
- writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
+ writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
}
const struct snd_soc_dai_ops acp_dmic_dai_ops = {
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 val, i;
if (!adata)
return IRQ_NONE;
- val = readl(adata->acp_base + ACP_EXTERNAL_INTR_STAT);
+ val = readl(ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
for (i = 0; i < ACP_MAX_STREAM; i++) {
stream = adata->stream[i];
if (stream && (val & stream->irq_bit)) {
- writel(stream->irq_bit, adata->acp_base + ACP_EXTERNAL_INTR_STAT);
+ writel(stream->irq_bit,
+ ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
snd_pcm_period_elapsed(stream->substream);
i2s_flag = 1;
break;
static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream)
{
+ struct acp_resource *rsrc = adata->rsrc;
u32 pte_reg, pte_size, reg_val;
/* Use ATU base Group5 */
stream->reg_offset = 0x02000000;
/* Group Enable */
- reg_val = ACP_SRAM_PTE_OFFSET;
+ reg_val = rsrc->sram_pte_offset;
writel(reg_val | BIT(31), adata->acp_base + pte_reg);
writel(PAGE_SIZE_4K_ENABLE, adata->acp_base + pte_size);
}
{
struct acp_stream *stream = adata->stream[cpu_id];
struct snd_pcm_substream *substream = stream->substream;
+ struct acp_resource *rsrc = adata->rsrc;
dma_addr_t addr = substream->dma_buffer.addr;
int num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
u32 low, high, val;
/* 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 + ACP_SCRATCH_REG_0 + val);
+ writel(low, adata->acp_base + rsrc->scratch_reg_offset + val);
high |= BIT(31);
- writel(high, adata->acp_base + ACP_SCRATCH_REG_0 + val + 4);
+ writel(high, adata->acp_base + rsrc->scratch_reg_offset + val + 4);
/* Move to next physically contiguous page */
val += 8;
}
runtime->private_data = stream;
- writel(1, adata->acp_base + ACP_EXTERNAL_INTR_ENB);
+ writel(1, ACP_EXTERNAL_INTR_ENB(adata));
return ret;
}
#define ACP_ERROR_MASK 0x20000000
#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
+static struct acp_resource rsrc = {
+ .offset = 20,
+ .no_of_ctrls = 1,
+ .irqp_used = 0,
+ .irq_reg_offset = 0x1800,
+ .i2s_pin_cfg_offset = 0x1400,
+ .i2s_mode = 0x04,
+ .scratch_reg_offset = 0x12800,
+ .sram_pte_offset = 0x02052800,
+};
+
static struct snd_soc_acpi_codecs amp_rt1019 = {
.num_codecs = 1,
.codecs = {"10EC1019"}
return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT);
}
-static void acp3x_enable_interrupts(void __iomem *base)
+static void acp3x_enable_interrupts(struct acp_dev_data *adata)
{
+ struct acp_resource *rsrc = adata->rsrc;
u32 ext_intr_ctrl;
- writel(0x01, base + ACP_EXTERNAL_INTR_ENB);
- ext_intr_ctrl = readl(base + ACP_EXTERNAL_INTR_CNTL);
+ writel(0x01, ACP_EXTERNAL_INTR_ENB(adata));
+ ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
ext_intr_ctrl |= ACP_ERROR_MASK;
- writel(ext_intr_ctrl, base + ACP_EXTERNAL_INTR_CNTL);
+ writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
}
-static void acp3x_disable_interrupts(void __iomem *base)
+static void acp3x_disable_interrupts(struct acp_dev_data *adata)
{
- writel(ACP_EXT_INTR_STAT_CLEAR_MASK, base + ACP_EXTERNAL_INTR_STAT);
- writel(0x00, base + ACP_EXTERNAL_INTR_ENB);
+ struct acp_resource *rsrc = adata->rsrc;
+
+ writel(ACP_EXT_INTR_STAT_CLEAR_MASK,
+ ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
+ writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
}
static int rn_acp_init(void __iomem *base)
if (ret)
return ret;
- acp3x_enable_interrupts(base);
-
return 0;
}
{
int ret = 0;
- acp3x_disable_interrupts(base);
-
/* Reset */
ret = acp3x_reset(base);
if (ret)
adata->dev = dev;
adata->dai_driver = acp_renoir_dai;
adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
+ adata->rsrc = &rsrc;
adata->machines = snd_soc_acpi_amd_acp_machines;
acp_machine_select(adata);
dev_set_drvdata(dev, adata);
+ acp3x_enable_interrupts(adata);
acp_platform_register(dev);
return 0;
static int 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;
int ret;
chip = dev_get_platdata(&pdev->dev);
+ acp3x_disable_interrupts(adata);
+
ret = rn_acp_deinit(chip->base);
if (ret)
dev_err(&pdev->dev, "ACP de-init Failed (%pe)\n", ERR_PTR(ret));
#define ACP3x_I2STDM_REG_END 0x1242410
#define ACP3x_BT_TDM_REG_START 0x1242800
#define ACP3x_BT_TDM_REG_END 0x1242810
-#define I2S_MODE 0x04
-#define I2S_RX_THRESHOLD 27
-#define I2S_TX_THRESHOLD 28
-#define BT_TX_THRESHOLD 26
-#define BT_RX_THRESHOLD 25
-#define ACP_SRAM_PTE_OFFSET 0x02052800
+#define THRESHOLD(bit, base) ((bit) + (base))
+#define I2S_RX_THRESHOLD(base) THRESHOLD(7, base)
+#define I2S_TX_THRESHOLD(base) THRESHOLD(8, base)
+#define BT_TX_THRESHOLD(base) THRESHOLD(6, base)
+#define BT_RX_THRESHOLD(base) THRESHOLD(5, base)
#define ACP_SRAM_SP_PB_PTE_OFFSET 0x0
#define ACP_SRAM_SP_CP_PTE_OFFSET 0x100
u32 fifo_offset;
};
+struct acp_resource {
+ int offset;
+ int no_of_ctrls;
+ int irqp_used;
+ u32 irq_reg_offset;
+ u32 i2s_pin_cfg_offset;
+ int i2s_mode;
+ u64 scratch_reg_offset;
+ u64 sram_pte_offset;
+};
+
struct acp_dev_data {
char *name;
struct device *dev;
struct snd_soc_acpi_mach *machines;
struct platform_device *mach_dev;
+
+ struct acp_resource *rsrc;
};
extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
#define ACP_SOFT_RESET 0x1000
#define ACP_CONTROL 0x1004
-#define ACP_EXTERNAL_INTR_ENB 0x1800
-#define ACP_EXTERNAL_INTR_CNTL 0x1804
-#define ACP_EXTERNAL_INTR_STAT 0x1808
-#define ACP_I2S_PIN_CONFIG 0x1400
-#define ACP_SCRATCH_REG_0 0x12800
+#define ACP_EXTERNAL_INTR_REG_ADDR(adata, offset, ctrl) \
+ (adata->acp_base + adata->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)
/* Registers from ACP_AUDIO_BUFFERS block */