[PATCH 00/12] Add i2s/tdm support for acp7.0 and acp7.1 platforms
1. Refactor acp generic driver to support all platforms. 2. Add i2s/tdm and support for acp7.0 and acp7.1 platforms.
Venkata Prasad Potturu (12): ASoC: amd: acp: Refactor TDM slots selction based on acp revision id ASoC: amd: acp: Refactor I2S dai driver ASoC: amd: acp: Update pcm hardware capabilities for acp6.3 platform ASoC: amd: acp: Add I2S TDM support for acp6.3 platform ASoC: amd: acp: Update pcm hardware capabilities for acp7.0 platform ASoC: amd: acp: Add I2S master clock generation support for acp7.0 platform ASoC: amd: acp: Set i2s clock for acp7.0 platform ASoC: amd: acp: Modify max channels and sample rate support for acp70 dai driver ASoC: amd: acp: Add I2S TDM support for acp7.0 platform ASoC: amd: acp: Add pte configuration for ACP7.0 platform ASoC: amd: acp: Add i2s master clock generation support for acp7.1 platform ASoC: amd: acp: Add I2S TDM support for acp7.1 platform
sound/soc/amd/acp/acp-i2s.c | 188 ++++++++++++++++++++------ sound/soc/amd/acp/acp-legacy-common.c | 32 ++--- sound/soc/amd/acp/acp-pdm.c | 7 +- sound/soc/amd/acp/acp-platform.c | 117 ++++++++++++++-- sound/soc/amd/acp/acp70.c | 73 +++++++--- sound/soc/amd/acp/amd.h | 24 ++-- sound/soc/amd/acp/chip_offset_byte.h | 84 +++++++----- 7 files changed, 387 insertions(+), 138 deletions(-)
Refactor TDM slots selection based on acp revision id.
Signed-off-by: Venkata Prasad Potturu venkataprasad.potturu@amd.com --- sound/soc/amd/acp/acp-i2s.c | 40 +++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 11 deletions(-)
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c index 97258b4cf89b..5d1d27078626 100644 --- a/sound/soc/amd/acp/acp-i2s.c +++ b/sound/soc/amd/acp/acp-i2s.c @@ -95,9 +95,11 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas { 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); switch (slot_width) { case SLOT_WIDTH_8: slot_len = 8; @@ -116,15 +118,23 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas return -EINVAL; }
- switch (slots) { - case 1 ... 7: - no_of_slots = slots; - break; - case 8: - no_of_slots = 0; + switch (chip->acp_rev) { + case ACP3X_DEV: + case ACP6X_DEV: + switch (slots) { + case 1 ... 7: + no_of_slots = slots; + break; + case 8: + no_of_slots = 0; + break; + default: + dev_err(dev, "Unsupported slots %d\n", slots); + return -EINVAL; + } break; default: - dev_err(dev, "Unsupported slots %d\n", slots); + dev_err(dev, "Unknown chip revision %d\n", chip->acp_rev); return -EINVAL; }
@@ -132,12 +142,20 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas
spin_lock_irq(&adata->acp_lock); list_for_each_entry(stream, &adata->stream_list, list) { - if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) - adata->tdm_tx_fmt[stream->dai_id - 1] = + switch (chip->acp_rev) { + case ACP3X_DEV: + case ACP6X_DEV: + if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) + adata->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] = + else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE) + adata->tdm_rx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 15) | (slot_len << 18); + break; + default: + dev_err(dev, "Unknown chip revision %d\n", chip->acp_rev); + return -EINVAL; + } } spin_unlock_irq(&adata->acp_lock); return 0;
All I2S instances are connected to different powertile form acp6.0 onwards, refactor dai driver to support all I2S instances for all acp platforms.
Signed-off-by: Venkata Prasad Potturu venkataprasad.potturu@amd.com --- sound/soc/amd/acp/acp-i2s.c | 49 ++++++++--------- sound/soc/amd/acp/acp-legacy-common.c | 32 +++++------ sound/soc/amd/acp/amd.h | 16 +++--- sound/soc/amd/acp/chip_offset_byte.h | 77 ++++++++++++++------------- 4 files changed, 90 insertions(+), 84 deletions(-)
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c index 5d1d27078626..aca99020120a 100644 --- a/sound/soc/amd/acp/acp-i2s.c +++ b/sound/soc/amd/acp/acp-i2s.c @@ -339,16 +339,16 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { switch (dai->driver->id) { case I2S_BT_INSTANCE: - water_val = ACP_BT_TX_INTR_WATERMARK_SIZE; + water_val = ACP_BT_TX_INTR_WATERMARK_SIZE(adata); reg_val = ACP_BTTDM_ITER; ier_val = ACP_BTTDM_IER; - buf_reg = ACP_BT_TX_RINGBUFSIZE; + buf_reg = ACP_BT_TX_RINGBUFSIZE(adata); break; case I2S_SP_INSTANCE: - water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE; + water_val = ACP_I2S_TX_INTR_WATERMARK_SIZE(adata); reg_val = ACP_I2STDM_ITER; ier_val = ACP_I2STDM_IER; - buf_reg = ACP_I2S_TX_RINGBUFSIZE; + buf_reg = ACP_I2S_TX_RINGBUFSIZE(adata); break; case I2S_HS_INSTANCE: water_val = ACP_HS_TX_INTR_WATERMARK_SIZE; @@ -363,16 +363,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; + water_val = ACP_BT_RX_INTR_WATERMARK_SIZE(adata); reg_val = ACP_BTTDM_IRER; ier_val = ACP_BTTDM_IER; - buf_reg = ACP_BT_RX_RINGBUFSIZE; + buf_reg = ACP_BT_RX_RINGBUFSIZE(adata); break; case I2S_SP_INSTANCE: - water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE; + water_val = ACP_I2S_RX_INTR_WATERMARK_SIZE(adata); reg_val = ACP_I2STDM_IRER; ier_val = ACP_I2STDM_IER; - buf_reg = ACP_I2S_RX_RINGBUFSIZE; + buf_reg = ACP_I2S_RX_RINGBUFSIZE(adata); break; case I2S_HS_INSTANCE: water_val = ACP_HS_RX_INTR_WATERMARK_SIZE; @@ -385,6 +385,7 @@ static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct return -EINVAL; } } + writel(period_bytes, adata->acp_base + water_val); writel(buf_size, adata->acp_base + buf_reg); if (rsrc->soc_mclk) @@ -463,43 +464,43 @@ 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; + reg_dma_size = ACP_I2S_TX_DMA_SIZE(adata); 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; + reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata); + reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata);
phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR); + writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR(adata)); } else { - reg_dma_size = ACP_I2S_RX_DMA_SIZE; + reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata); 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; + reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata); + reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata); phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR); + writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR(adata)); } break; case I2S_BT_INSTANCE: if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - reg_dma_size = ACP_BT_TX_DMA_SIZE; + reg_dma_size = ACP_BT_TX_DMA_SIZE(adata); 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; + reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata); + reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata);
phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR); + writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR(adata)); } else { - reg_dma_size = ACP_BT_RX_DMA_SIZE; + reg_dma_size = ACP_BT_RX_DMA_SIZE(adata); 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; + reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata); + reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata);
phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR); + writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR(adata)); } break; case I2S_HS_INSTANCE: diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c index 3cc083fac837..be01b178172e 100644 --- a/sound/soc/amd/acp/acp-legacy-common.c +++ b/sound/soc/amd/acp/acp-legacy-common.c @@ -113,40 +113,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; + reg_dma_size = ACP_I2S_TX_DMA_SIZE(adata); 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; + reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata); + reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata); phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR); + writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR(adata)); } else { - reg_dma_size = ACP_I2S_RX_DMA_SIZE; + reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata); 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; + reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata); + reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata); phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR); + writel(phy_addr, adata->acp_base + ACP_I2S_RX_RINGBUFADDR(adata)); } break; case I2S_BT_INSTANCE: if (dir == SNDRV_PCM_STREAM_PLAYBACK) { - reg_dma_size = ACP_BT_TX_DMA_SIZE; + reg_dma_size = ACP_BT_TX_DMA_SIZE(adata); 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; + reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata); + reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata); phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR); + writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR(adata)); } else { - reg_dma_size = ACP_BT_RX_DMA_SIZE; + reg_dma_size = ACP_BT_RX_DMA_SIZE(adata); 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; + reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata); + reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata); phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; - writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR); + writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR(adata)); } break; case I2S_HS_INSTANCE: diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 4f0cd7dd04e5..9fb4e234d518 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -259,12 +259,12 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int if (direction == SNDRV_PCM_STREAM_PLAYBACK) { switch (dai_id) { case I2S_BT_INSTANCE: - high = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH); - low = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW); + high = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH(adata)); + low = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW(adata)); break; case I2S_SP_INSTANCE: - high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH); - low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW); + high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH(adata)); + low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW(adata)); break; case I2S_HS_INSTANCE: high = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH); @@ -277,12 +277,12 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int } else { switch (dai_id) { case I2S_BT_INSTANCE: - high = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH); - low = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW); + high = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH(adata)); + low = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW(adata)); break; case I2S_SP_INSTANCE: - high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH); - low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW); + high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH(adata)); + low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW(adata)); break; case I2S_HS_INSTANCE: high = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH); diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h index 18da734c0e9e..97b8b49f1e64 100644 --- a/sound/soc/amd/acp/chip_offset_byte.h +++ b/sound/soc/amd/acp/chip_offset_byte.h @@ -32,42 +32,47 @@
/* Registers from ACP_AUDIO_BUFFERS block */
-#define ACP_I2S_RX_RINGBUFADDR 0x2000 -#define ACP_I2S_RX_RINGBUFSIZE 0x2004 -#define ACP_I2S_RX_LINKPOSITIONCNTR 0x2008 -#define ACP_I2S_RX_FIFOADDR 0x200C -#define ACP_I2S_RX_FIFOSIZE 0x2010 -#define ACP_I2S_RX_DMA_SIZE 0x2014 -#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x2018 -#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x201C -#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x2020 -#define ACP_I2S_TX_RINGBUFADDR 0x2024 -#define ACP_I2S_TX_RINGBUFSIZE 0x2028 -#define ACP_I2S_TX_LINKPOSITIONCNTR 0x202C -#define ACP_I2S_TX_FIFOADDR 0x2030 -#define ACP_I2S_TX_FIFOSIZE 0x2034 -#define ACP_I2S_TX_DMA_SIZE 0x2038 -#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x203C -#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x2040 -#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x2044 -#define ACP_BT_RX_RINGBUFADDR 0x2048 -#define ACP_BT_RX_RINGBUFSIZE 0x204C -#define ACP_BT_RX_LINKPOSITIONCNTR 0x2050 -#define ACP_BT_RX_FIFOADDR 0x2054 -#define ACP_BT_RX_FIFOSIZE 0x2058 -#define ACP_BT_RX_DMA_SIZE 0x205C -#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x2060 -#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x2064 -#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x2068 -#define ACP_BT_TX_RINGBUFADDR 0x206C -#define ACP_BT_TX_RINGBUFSIZE 0x2070 -#define ACP_BT_TX_LINKPOSITIONCNTR 0x2074 -#define ACP_BT_TX_FIFOADDR 0x2078 -#define ACP_BT_TX_FIFOSIZE 0x207C -#define ACP_BT_TX_DMA_SIZE 0x2080 -#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x2084 -#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x2088 -#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x208C +#define ACP_I2S_REG_ADDR(acp_adata, addr) \ + ((addr) + (acp_adata->rsrc->irqp_used * \ + acp_adata->rsrc->irq_reg_offset)) + +#define ACP_I2S_RX_RINGBUFADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2000) +#define ACP_I2S_RX_RINGBUFSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2004) +#define ACP_I2S_RX_LINKPOSITIONCNTR(adata) ACP_I2S_REG_ADDR(adata, 0x2008) +#define ACP_I2S_RX_FIFOADDR(adata) ACP_I2S_REG_ADDR(adata, 0x200C) +#define ACP_I2S_RX_FIFOSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2010) +#define ACP_I2S_RX_DMA_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2014) +#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH(adata) ACP_I2S_REG_ADDR(adata, 0x2018) +#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW(adata) ACP_I2S_REG_ADDR(adata, 0x201C) +#define ACP_I2S_RX_INTR_WATERMARK_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2020) +#define ACP_I2S_TX_RINGBUFADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2024) +#define ACP_I2S_TX_RINGBUFSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2028) +#define ACP_I2S_TX_LINKPOSITIONCNTR(adata) ACP_I2S_REG_ADDR(adata, 0x202C) +#define ACP_I2S_TX_FIFOADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2030) +#define ACP_I2S_TX_FIFOSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2034) +#define ACP_I2S_TX_DMA_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2038) +#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH(adata) ACP_I2S_REG_ADDR(adata, 0x203C) +#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW(adata) ACP_I2S_REG_ADDR(adata, 0x2040) +#define ACP_I2S_TX_INTR_WATERMARK_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2044) +#define ACP_BT_RX_RINGBUFADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2048) +#define ACP_BT_RX_RINGBUFSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x204C) +#define ACP_BT_RX_LINKPOSITIONCNTR(adata) ACP_I2S_REG_ADDR(adata, 0x2050) +#define ACP_BT_RX_FIFOADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2054) +#define ACP_BT_RX_FIFOSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2058) +#define ACP_BT_RX_DMA_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x205C) +#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH(adata) ACP_I2S_REG_ADDR(adata, 0x2060) +#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW(adata) ACP_I2S_REG_ADDR(adata, 0x2064) +#define ACP_BT_RX_INTR_WATERMARK_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2068) +#define ACP_BT_TX_RINGBUFADDR(adata) ACP_I2S_REG_ADDR(adata, 0x206C) +#define ACP_BT_TX_RINGBUFSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2070) +#define ACP_BT_TX_LINKPOSITIONCNTR(adata) ACP_I2S_REG_ADDR(adata, 0x2074) +#define ACP_BT_TX_FIFOADDR(adata) ACP_I2S_REG_ADDR(adata, 0x2078) +#define ACP_BT_TX_FIFOSIZE(adata) ACP_I2S_REG_ADDR(adata, 0x207C) +#define ACP_BT_TX_DMA_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x2080) +#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH(adata) ACP_I2S_REG_ADDR(adata, 0x2084) +#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW(adata) ACP_I2S_REG_ADDR(adata, 0x2088) +#define ACP_BT_TX_INTR_WATERMARK_SIZE(adata) ACP_I2S_REG_ADDR(adata, 0x208C) + #define ACP_HS_RX_RINGBUFADDR 0x3A90 #define ACP_HS_RX_RINGBUFSIZE 0x3A94 #define ACP_HS_RX_LINKPOSITIONCNTR 0x3A98
Update pcm hardware capabilities based on acp revision id.
Signed-off-by: Venkata Prasad Potturu venkataprasad.potturu@amd.com --- sound/soc/amd/acp/acp-platform.c | 61 +++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 5 deletions(-)
diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index 4f409cd09c11..238b4f648f44 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -68,6 +68,46 @@ static const struct snd_pcm_hardware acp_pcm_hardware_capture = { .periods_max = CAPTURE_MAX_NUM_PERIODS, };
+static const struct snd_pcm_hardware acp6x_pcm_hardware_playback = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 32, + .rates = SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE, + .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE, + .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE, + .periods_min = PLAYBACK_MIN_NUM_PERIODS, + .periods_max = PLAYBACK_MAX_NUM_PERIODS, +}; + +static const struct snd_pcm_hardware acp6x_pcm_hardware_capture = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + .channels_min = 2, + .channels_max = 32, + .rates = SNDRV_PCM_RATE_8000_192000, + .rate_min = 8000, + .rate_max = 192000, + .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE, + .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, + .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE, + .periods_min = CAPTURE_MIN_NUM_PERIODS, + .periods_max = CAPTURE_MAX_NUM_PERIODS, +}; + int acp_machine_select(struct acp_dev_data *adata) { struct snd_soc_acpi_mach *mach; @@ -183,6 +223,7 @@ 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;
@@ -191,11 +232,21 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs return -ENOMEM;
stream->substream = substream; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - runtime->hw = acp_pcm_hardware_playback; - else - runtime->hw = acp_pcm_hardware_capture; + chip = dev_get_platdata(dev); + switch (chip->acp_rev) { + case ACP63_DEV: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + runtime->hw = acp6x_pcm_hardware_playback; + else + runtime->hw = acp6x_pcm_hardware_capture; + break; + default: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + runtime->hw = acp_pcm_hardware_playback; + else + runtime->hw = acp_pcm_hardware_capture; + break; + }
ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, DMA_SIZE); if (ret) {
Add slots selection and 32-channels TDM support for acp6.3 platform.
Signed-off-by: Venkata Prasad Potturu venkataprasad.potturu@amd.com --- sound/soc/amd/acp/acp-i2s.c | 56 +++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c index aca99020120a..eceffc69bf3e 100644 --- a/sound/soc/amd/acp/acp-i2s.c +++ b/sound/soc/amd/acp/acp-i2s.c @@ -133,6 +133,19 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas return -EINVAL; } break; + case ACP63_DEV: + switch (slots) { + case 1 ... 31: + no_of_slots = slots; + break; + case 32: + no_of_slots = 0; + break; + default: + dev_err(dev, "Unsupported slots %d\n", slots); + return -EINVAL; + } + break; default: dev_err(dev, "Unknown chip revision %d\n", chip->acp_rev); return -EINVAL; @@ -152,6 +165,14 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas adata->tdm_rx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 15) | (slot_len << 18); break; + case ACP63_DEV: + if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) + adata->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] = + FRM_LEN | (slots << 13) | (slot_len << 18); + break; default: dev_err(dev, "Unknown chip revision %d\n", chip->acp_rev); return -EINVAL; @@ -314,6 +335,41 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_ default: return -EINVAL; } + + switch (params_rate(params)) { + case 8000: + case 16000: + case 24000: + case 48000: + case 96000: + case 192000: + switch (params_channels(params)) { + case 2: + break; + case 4: + bclk_div_val = bclk_div_val >> 1; + lrclk_div_val = lrclk_div_val << 1; + break; + case 8: + bclk_div_val = bclk_div_val >> 2; + lrclk_div_val = lrclk_div_val << 2; + break; + case 16: + bclk_div_val = bclk_div_val >> 3; + lrclk_div_val = lrclk_div_val << 3; + break; + case 32: + bclk_div_val = bclk_div_val >> 4; + lrclk_div_val = lrclk_div_val << 4; + break; + default: + dev_err(dev, "Unsupported channels %#x\n", + params_channels(params)); + } + break; + default: + break; + } adata->lrclk_div = lrclk_div_val; adata->bclk_div = bclk_div_val; }
Update pcm hardware capabilities for acp7.0 platform.
Signed-off-by: Venkata Prasad Potturu venkataprasad.potturu@amd.com --- sound/soc/amd/acp/acp-platform.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index 238b4f648f44..55573bdd5ef4 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -235,6 +235,7 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs chip = dev_get_platdata(dev); switch (chip->acp_rev) { case ACP63_DEV: + case ACP70_DEV: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) runtime->hw = acp6x_pcm_hardware_playback; else
Add I2S master clock generation support for acp7.0 platforms.
Signed-off-by: Venkata Prasad Potturu venkataprasad.potturu@amd.com --- sound/soc/amd/acp/acp70.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index 81636faa22cd..a9be059889b7 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -25,6 +25,9 @@
#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, @@ -134,12 +137,27 @@ 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; + + smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1507, 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); if (!chip || !chip->base) { @@ -191,6 +209,12 @@ static int acp_acp70_audio_probe(struct platform_device *pdev) acp_machine_select(adata);
dev_set_drvdata(dev, adata); + + ret = acp70_i2s_master_clock_generate(adata); + if (ret) { + dev_err(&pdev->dev, "Failed to set I2S master clock as 196.608MHz\n"); + return ret; + } acp_enable_interrupts(adata); acp_platform_register(dev); pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS);
Set i2s bclk and lrclk for acp7.0 platform.
Signed-off-by: Venkata Prasad Potturu venkataprasad.potturu@amd.com --- sound/soc/amd/acp/acp-i2s.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c index eceffc69bf3e..31475a4dbced 100644 --- a/sound/soc/amd/acp/acp-i2s.c +++ b/sound/soc/amd/acp/acp-i2s.c @@ -60,6 +60,7 @@ static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id)
switch (chip->acp_rev) { case ACP63_DEV: + case ACP70_DEV: val |= FIELD_PREP(ACP63_LRCLK_DIV_FIELD, adata->lrclk_div); val |= FIELD_PREP(ACP63_BCLK_DIV_FIELD, adata->bclk_div); break;
Modify max channels and max sample rate support in the dai driver for acp7.0 platform.
Signed-off-by: Venkata Prasad Potturu venkataprasad.potturu@amd.com --- sound/soc/amd/acp/acp70.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index a9be059889b7..a662c7db7506 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -52,23 +52,23 @@ static struct snd_soc_dai_driver acp70_dai[] = { .id = I2S_SP_INSTANCE, .playback = { .stream_name = "I2S SP Playback", - .rates = SNDRV_PCM_RATE_8000_96000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, - .rate_max = 96000, + .rate_max = 192000, }, .capture = { .stream_name = "I2S SP Capture", - .rates = SNDRV_PCM_RATE_8000_48000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 2, + .channels_max = 32, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &asoc_acp_cpu_dai_ops, }, @@ -77,23 +77,23 @@ static struct snd_soc_dai_driver acp70_dai[] = { .id = I2S_BT_INSTANCE, .playback = { .stream_name = "I2S BT Playback", - .rates = SNDRV_PCM_RATE_8000_96000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, - .rate_max = 96000, + .rate_max = 192000, }, .capture = { .stream_name = "I2S BT Capture", - .rates = SNDRV_PCM_RATE_8000_48000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 2, + .channels_max = 32, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &asoc_acp_cpu_dai_ops, }, @@ -102,23 +102,23 @@ static struct snd_soc_dai_driver acp70_dai[] = { .id = I2S_HS_INSTANCE, .playback = { .stream_name = "I2S HS Playback", - .rates = SNDRV_PCM_RATE_8000_96000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, - .rate_max = 96000, + .rate_max = 192000, }, .capture = { .stream_name = "I2S HS Capture", - .rates = SNDRV_PCM_RATE_8000_48000, + .rates = SNDRV_PCM_RATE_8000_192000, .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, - .channels_max = 8, + .channels_max = 32, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &asoc_acp_cpu_dai_ops, },
Add acp70 revision id to support I2S TDM.
Signed-off-by: Venkata Prasad Potturu venkataprasad.potturu@amd.com --- sound/soc/amd/acp/acp-i2s.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c index 31475a4dbced..2a23c52eb512 100644 --- a/sound/soc/amd/acp/acp-i2s.c +++ b/sound/soc/amd/acp/acp-i2s.c @@ -135,6 +135,7 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas } break; case ACP63_DEV: + case ACP70_DEV: switch (slots) { case 1 ... 31: no_of_slots = slots; @@ -167,6 +168,7 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas FRM_LEN | (slots << 15) | (slot_len << 18); break; case ACP63_DEV: + case ACP70_DEV: if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) adata->tdm_tx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 13) | (slot_len << 18);
Add page table entry configurations to support higher sample rate streams with multiple channels for ACP7.0 platforms.
Signed-off-by: Venkata Prasad Potturu venkataprasad.potturu@amd.com --- sound/soc/amd/acp/acp-i2s.c | 33 +++++++++++++---- sound/soc/amd/acp/acp-pdm.c | 7 +++- sound/soc/amd/acp/acp-platform.c | 53 +++++++++++++++++++++++----- sound/soc/amd/acp/acp70.c | 4 +-- sound/soc/amd/acp/amd.h | 8 +++++ sound/soc/amd/acp/chip_offset_byte.h | 7 ++++ 6 files changed, 94 insertions(+), 18 deletions(-)
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c index 2a23c52eb512..74f2ad62e596 100644 --- a/sound/soc/amd/acp/acp-i2s.c +++ b/sound/soc/amd/acp/acp-i2s.c @@ -514,12 +514,14 @@ 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_chip_info *chip; 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; unsigned int dir = substream->stream;
+ chip = dev_get_platdata(dev); switch (dai->driver->id) { case I2S_SP_INSTANCE: if (dir == SNDRV_PCM_STREAM_PLAYBACK) { @@ -529,7 +531,10 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d reg_fifo_addr = ACP_I2S_TX_FIFOADDR(adata); reg_fifo_size = ACP_I2S_TX_FIFOSIZE(adata);
- phy_addr = I2S_SP_TX_MEM_WINDOW_START + stream->reg_offset; + if (chip->acp_rev >= ACP70_DEV) + 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)); } else { reg_dma_size = ACP_I2S_RX_DMA_SIZE(adata); @@ -537,7 +542,11 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d SP_CAPT_FIFO_ADDR_OFFSET; reg_fifo_addr = ACP_I2S_RX_FIFOADDR(adata); reg_fifo_size = ACP_I2S_RX_FIFOSIZE(adata); - phy_addr = I2S_SP_RX_MEM_WINDOW_START + stream->reg_offset; + + if (chip->acp_rev >= ACP70_DEV) + 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)); } break; @@ -549,7 +558,10 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d reg_fifo_addr = ACP_BT_TX_FIFOADDR(adata); reg_fifo_size = ACP_BT_TX_FIFOSIZE(adata);
- phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; + if (chip->acp_rev >= ACP70_DEV) + 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)); } else { reg_dma_size = ACP_BT_RX_DMA_SIZE(adata); @@ -558,7 +570,10 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d reg_fifo_addr = ACP_BT_RX_FIFOADDR(adata); reg_fifo_size = ACP_BT_RX_FIFOSIZE(adata);
- phy_addr = I2S_BT_TX_MEM_WINDOW_START + stream->reg_offset; + if (chip->acp_rev >= ACP70_DEV) + 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)); } break; @@ -570,7 +585,10 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d 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; + if (chip->acp_rev >= ACP70_DEV) + 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); } else { reg_dma_size = ACP_HS_RX_DMA_SIZE; @@ -579,7 +597,10 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d 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; + if (chip->acp_rev >= ACP70_DEV) + 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); } break; diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c index bb79269c2fc1..22dd8988d005 100644 --- a/sound/soc/amd/acp/acp-pdm.c +++ b/sound/soc/amd/acp/acp-pdm.c @@ -31,9 +31,11 @@ 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); @@ -45,7 +47,10 @@ static int acp_dmic_prepare(struct snd_pcm_substream *substream, size_dmic = frames_to_bytes(substream->runtime, substream->runtime->buffer_size);
- physical_addr = stream->reg_offset + MEM_WINDOW_START; + if (chip->acp_rev >= ACP70_DEV) + physical_addr = ACP7x_DMIC_MEM_WINDOW_START; + else + physical_addr = stream->reg_offset + MEM_WINDOW_START;
/* Init DMIC Ring buffer */ writel(physical_addr, adata->acp_base + ACP_WOV_RX_RINGBUFADDR); diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index 55573bdd5ef4..6ef9baeed74a 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -177,17 +177,20 @@ static irqreturn_t i2s_irq_handler(int irq, void *data) 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; + u32 reg_val;
- /* Use ATU base Group5 */ - pte_reg = ACPAXI2AXI_ATU_BASE_ADDR_GRP_5; - pte_size = ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5; + reg_val = rsrc->sram_pte_offset; stream->reg_offset = 0x02000000;
- /* Group Enable */ - 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); + 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 + 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 | 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(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL); } EXPORT_SYMBOL_NS_GPL(config_pte_for_stream, SND_SOC_ACP_COMMON); @@ -201,7 +204,39 @@ void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int s u32 low, high, val; u16 page_idx;
- val = stream->pte_offset; + switch (adata->platform) { + case ACP70: + switch (stream->dai_id) { + case I2S_SP_INSTANCE: + if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) + val = 0x0; + else + val = 0x1000; + break; + case I2S_BT_INSTANCE: + if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) + val = 0x2000; + else + val = 0x3000; + break; + case I2S_HS_INSTANCE: + if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) + val = 0x4000; + else + val = 0x5000; + break; + case DMIC_INSTANCE: + val = 0x6000; + break; + default: + dev_err(adata->dev, "Invalid dai id %x\n", stream->dai_id); + break; + } + break; + default: + val = stream->pte_offset; + break; + }
for (page_idx = 0; page_idx < num_pages; page_idx++) { /* Load the low address of page int ACP SRAM through SRBM */ diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index a662c7db7506..3b3bd15964fc 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -34,8 +34,8 @@ static struct acp_resource rsrc = { .irqp_used = 1, .soc_mclk = true, .irq_reg_offset = 0x1a00, - .scratch_reg_offset = 0x12800, - .sram_pte_offset = 0x03802800, + .scratch_reg_offset = 0x10000, + .sram_pte_offset = 0x03800000, };
static struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_acp_machines[] = { diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h index 9fb4e234d518..854269fea875 100644 --- a/sound/soc/amd/acp/amd.h +++ b/sound/soc/amd/acp/amd.h @@ -62,6 +62,14 @@ #define I2S_HS_TX_MEM_WINDOW_START 0x40A0000 #define I2S_HS_RX_MEM_WINDOW_START 0x40C0000
+#define ACP7x_I2S_SP_TX_MEM_WINDOW_START 0x4000000 +#define ACP7x_I2S_SP_RX_MEM_WINDOW_START 0x4200000 +#define ACP7x_I2S_BT_TX_MEM_WINDOW_START 0x4400000 +#define ACP7x_I2S_BT_RX_MEM_WINDOW_START 0x4600000 +#define ACP7x_I2S_HS_TX_MEM_WINDOW_START 0x4800000 +#define ACP7x_I2S_HS_RX_MEM_WINDOW_START 0x4A00000 +#define ACP7x_DMIC_MEM_WINDOW_START 0x4C00000 + #define SP_PB_FIFO_ADDR_OFFSET 0x500 #define SP_CAPT_FIFO_ADDR_OFFSET 0x700 #define BT_PB_FIFO_ADDR_OFFSET 0x900 diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h index 97b8b49f1e64..117ea63e85c6 100644 --- a/sound/soc/amd/acp/chip_offset_byte.h +++ b/sound/soc/amd/acp/chip_offset_byte.h @@ -12,9 +12,16 @@ #define _ACP_IP_OFFSET_HEADER
#define ACPAXI2AXI_ATU_CTRL 0xC40 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0xC00 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0xC04 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0xC08 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0xC0C #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0xC20 #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0xC24
+#define GRP1_OFFSET 0x0 +#define GRP2_OFFSET 0x4000 + #define ACP_PGFSM_CONTROL 0x141C #define ACP_PGFSM_STATUS 0x1420 #define ACP_SOFT_RESET 0x1000
Add i2s master generation support for acp7.1 platform based on pci device id.
Signed-off-by: Venkata Prasad Potturu venkataprasad.potturu@amd.com --- sound/soc/amd/acp/acp70.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c index 3b3bd15964fc..1b0b59a22924 100644 --- a/sound/soc/amd/acp/acp70.c +++ b/sound/soc/amd/acp/acp70.c @@ -140,8 +140,17 @@ 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->platform == ACP70) + device_id = 0x1507; + else if (adata->platform == ACP71) + device_id = 0x1122; + else + return -ENODEV; + + smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, device_id, NULL);
- smn_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1507, NULL); if (!smn_dev) return -ENODEV;
Add acp71 revision id to support i2s/tdm mode.
Signed-off-by: Venkata Prasad Potturu venkataprasad.potturu@amd.com --- sound/soc/amd/acp/acp-i2s.c | 3 +++ sound/soc/amd/acp/acp-platform.c | 2 ++ 2 files changed, 5 insertions(+)
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c index 74f2ad62e596..56ce9e4b6acc 100644 --- a/sound/soc/amd/acp/acp-i2s.c +++ b/sound/soc/amd/acp/acp-i2s.c @@ -61,6 +61,7 @@ static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id) switch (chip->acp_rev) { case ACP63_DEV: case ACP70_DEV: + case ACP71_DEV: val |= FIELD_PREP(ACP63_LRCLK_DIV_FIELD, adata->lrclk_div); val |= FIELD_PREP(ACP63_BCLK_DIV_FIELD, adata->bclk_div); break; @@ -136,6 +137,7 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas break; case ACP63_DEV: case ACP70_DEV: + case ACP71_DEV: switch (slots) { case 1 ... 31: no_of_slots = slots; @@ -169,6 +171,7 @@ static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mas break; case ACP63_DEV: case ACP70_DEV: + case ACP71_DEV: if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK) adata->tdm_tx_fmt[stream->dai_id - 1] = FRM_LEN | (slots << 13) | (slot_len << 18); diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c index 6ef9baeed74a..ae63b2e693ab 100644 --- a/sound/soc/amd/acp/acp-platform.c +++ b/sound/soc/amd/acp/acp-platform.c @@ -206,6 +206,7 @@ void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int s
switch (adata->platform) { case ACP70: + case ACP71: switch (stream->dai_id) { case I2S_SP_INSTANCE: if (stream->dir == SNDRV_PCM_STREAM_PLAYBACK) @@ -271,6 +272,7 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs switch (chip->acp_rev) { case ACP63_DEV: case ACP70_DEV: + case ACP71_DEV: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) runtime->hw = acp6x_pcm_hardware_playback; else
On Tue, 03 Sep 2024 17:04:15 +0530, Venkata Prasad Potturu wrote:
- Refactor acp generic driver to support all platforms.
- Add i2s/tdm and support for acp7.0 and acp7.1 platforms.
Venkata Prasad Potturu (12): ASoC: amd: acp: Refactor TDM slots selction based on acp revision id ASoC: amd: acp: Refactor I2S dai driver ASoC: amd: acp: Update pcm hardware capabilities for acp6.3 platform ASoC: amd: acp: Add I2S TDM support for acp6.3 platform ASoC: amd: acp: Update pcm hardware capabilities for acp7.0 platform ASoC: amd: acp: Add I2S master clock generation support for acp7.0 platform ASoC: amd: acp: Set i2s clock for acp7.0 platform ASoC: amd: acp: Modify max channels and sample rate support for acp70 dai driver ASoC: amd: acp: Add I2S TDM support for acp7.0 platform ASoC: amd: acp: Add pte configuration for ACP7.0 platform ASoC: amd: acp: Add i2s master clock generation support for acp7.1 platform ASoC: amd: acp: Add I2S TDM support for acp7.1 platform
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[01/12] ASoC: amd: acp: Refactor TDM slots selction based on acp revision id commit: cd60dec8994cf0626faf80a67be9350ae335f7e9 [02/12] ASoC: amd: acp: Refactor I2S dai driver commit: 093184a3fe443f31a13ffa5d8d6d29ae68a4335d [03/12] ASoC: amd: acp: Update pcm hardware capabilities for acp6.3 platform commit: 973e9edea93943924638040f9c6eb849163bd421 [04/12] ASoC: amd: acp: Add I2S TDM support for acp6.3 platform commit: 13aeb56e6dacaa392cde42df86096dfdbeef5ac4 [05/12] ASoC: amd: acp: Update pcm hardware capabilities for acp7.0 platform commit: 7a040cc5579708a327b2d82caa26ab9a02623343 [06/12] ASoC: amd: acp: Add I2S master clock generation support for acp7.0 platform commit: fb2eaec6a38d853437c4a83b0c7168ef77536094 [07/12] ASoC: amd: acp: Set i2s clock for acp7.0 platform commit: 13073ed06a9f0234033d31e0ccba1e3167d500a3 [08/12] ASoC: amd: acp: Modify max channels and sample rate support for acp70 dai driver commit: b24df4fa40cc236ccea3de74d9cdb25c2906013b [09/12] ASoC: amd: acp: Add I2S TDM support for acp7.0 platform commit: b80d5a0c875fa0a708be24260d8f160d31273b1b [10/12] ASoC: amd: acp: Add pte configuration for ACP7.0 platform commit: f6f7d25b11033bdbf25d800572c003fced21a035 [11/12] ASoC: amd: acp: Add i2s master clock generation support for acp7.1 platform commit: 1150c18ba35376518b6ed9af3e96c671336fa5c7 [12/12] ASoC: amd: acp: Add I2S TDM support for acp7.1 platform commit: 3f600592fa0ca1599326e20aa22e845de5fc8ac5
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (2)
-
Mark Brown
-
Venkata Prasad Potturu