Unverified Commit b24484c1 authored by V sujith kumar Reddy's avatar V sujith kumar Reddy Committed by Mark Brown
Browse files

ASoC: amd: acp: ACP code generic to support newer platforms



ADD Generic code to support to newer platforms, add
control threshold, irq control macros ,added structure for register
offset differences.

Signed-off-by: default avatarV sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>
Link: https://lore.kernel.org/r/20220707161142.491034-3-Vsujithkumar.Reddy@amd.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent ac2606df
Loading
Loading
Loading
Loading
+20 −14
Original line number Diff line number Diff line
@@ -199,6 +199,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
{
	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;
@@ -208,7 +209,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
	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;
@@ -217,7 +218,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
			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;
@@ -228,7 +229,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
	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;
@@ -237,7 +238,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
			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;
@@ -255,11 +256,13 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
	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;
}
@@ -268,28 +271,30 @@ 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;
	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;
		}
@@ -319,6 +324,7 @@ int asoc_acp_i2s_probe(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;
	unsigned int val;

	if (!adata->acp_base) {
@@ -326,8 +332,8 @@ int asoc_acp_i2s_probe(struct snd_soc_dai *dai)
		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;
	}
+4 −4
Original line number Diff line number Diff line
@@ -160,9 +160,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(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;
}
@@ -175,9 +175,9 @@ static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream,
	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 = {
+10 −6
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ 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 val, i;
@@ -98,12 +99,13 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
	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;
@@ -118,6 +120,7 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)

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 */
@@ -126,7 +129,7 @@ static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream
	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);
}
@@ -135,6 +138,7 @@ static void config_acp_dma(struct acp_dev_data *adata, int cpu_id, int 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;
@@ -146,9 +150,9 @@ static void config_acp_dma(struct acp_dev_data *adata, int cpu_id, int size)
		/* 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;
@@ -187,7 +191,7 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
	}
	runtime->private_data = stream;

	writel(1, adata->acp_base + ACP_EXTERNAL_INTR_ENB);
	writel(1, ACP_EXTERNAL_INTR_ENB(adata));

	return ret;
}
+27 −11
Original line number Diff line number Diff line
@@ -39,6 +39,17 @@
#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"}
@@ -186,20 +197,24 @@ static int acp3x_reset(void __iomem *base)
	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)
@@ -218,8 +233,6 @@ static int rn_acp_init(void __iomem *base)
	if (ret)
		return ret;

	acp3x_enable_interrupts(base);

	return 0;
}

@@ -227,8 +240,6 @@ static int rn_acp_deinit(void __iomem *base)
{
	int ret = 0;

	acp3x_disable_interrupts(base);

	/* Reset */
	ret = acp3x_reset(base);
	if (ret)
@@ -290,11 +301,13 @@ static int renoir_audio_probe(struct platform_device *pdev)
	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;
@@ -303,11 +316,14 @@ static int renoir_audio_probe(struct platform_device *pdev)
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));
+18 −6
Original line number Diff line number Diff line
@@ -32,13 +32,12 @@
#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
@@ -92,6 +91,17 @@ struct acp_stream {
	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;
@@ -106,6 +116,8 @@ struct acp_dev_data {

	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;
Loading