[PATCH 1/1] ASoC: dwc: add DMA handshake control
DMA mode uses hardware handshake signals. DMACR register is used to enable the DMA Controller interface operation. So add DMA enable/disable to i2s_start()/i2s_stop() functions if using DMA mode.
Signed-off-by: Maxim Kochetkov fido_max@inbox.ru --- sound/soc/dwc/dwc-i2s.c | 39 +++++++++++++++++++++++++++++++++++++-- sound/soc/dwc/local.h | 6 ++++++ 2 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/sound/soc/dwc/dwc-i2s.c b/sound/soc/dwc/dwc-i2s.c index 9e7065dd854c..02b9894e99a7 100644 --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -150,19 +150,51 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id) return IRQ_NONE; }
+static void i2s_enable_dma(struct dw_i2s_dev *dev, u32 stream) +{ + u32 dma_reg = i2s_read_reg(dev->i2s_base, I2S_DMACR); + + /* Enable DMA handshake for stream */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + dma_reg |= I2S_DMAEN_TXBLOCK; + else + dma_reg |= I2S_DMAEN_RXBLOCK; + + i2s_write_reg(dev->i2s_base, I2S_DMACR, dma_reg); +} + +static void i2s_disable_dma(struct dw_i2s_dev *dev, u32 stream) +{ + u32 dma_reg = i2s_read_reg(dev->i2s_base, I2S_DMACR); + + /* Disable DMA handshake for stream */ + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + dma_reg &= ~I2S_DMAEN_TXBLOCK; + i2s_write_reg(dev->i2s_base, I2S_RTXDMA, 1); + } else { + dma_reg &= ~I2S_DMAEN_RXBLOCK; + i2s_write_reg(dev->i2s_base, I2S_RRXDMA, 1); + } + i2s_write_reg(dev->i2s_base, I2S_DMACR, dma_reg); +} + static void i2s_start(struct dw_i2s_dev *dev, struct snd_pcm_substream *substream) { struct i2s_clk_config_data *config = &dev->config;
i2s_write_reg(dev->i2s_base, IER, 1); - i2s_enable_irqs(dev, substream->stream, config->chan_nr);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) i2s_write_reg(dev->i2s_base, ITER, 1); else i2s_write_reg(dev->i2s_base, IRER, 1);
+ if (dev->use_pio) + i2s_enable_irqs(dev, substream->stream, config->chan_nr); + else + i2s_enable_dma(dev, substream->stream); + i2s_write_reg(dev->i2s_base, CER, 1); }
@@ -176,7 +208,10 @@ static void i2s_stop(struct dw_i2s_dev *dev, else i2s_write_reg(dev->i2s_base, IRER, 0);
- i2s_disable_irqs(dev, substream->stream, 8); + if (dev->use_pio) + i2s_disable_irqs(dev, substream->stream, 8); + else + i2s_disable_dma(dev, substream->stream);
if (!dev->active) { i2s_write_reg(dev->i2s_base, CER, 0); diff --git a/sound/soc/dwc/local.h b/sound/soc/dwc/local.h index d64bd4f8fd34..ba4e397099be 100644 --- a/sound/soc/dwc/local.h +++ b/sound/soc/dwc/local.h @@ -53,6 +53,12 @@ #define I2S_COMP_VERSION 0x01F8 #define I2S_COMP_TYPE 0x01FC
+#define I2S_RRXDMA 0x01C4 +#define I2S_RTXDMA 0x01CC +#define I2S_DMACR 0x0200 +#define I2S_DMAEN_RXBLOCK (1 << 16) +#define I2S_DMAEN_TXBLOCK (1 << 17) + /* * Component parameter register fields - define the I2S block's * configuration.
On Tue, 13 Jun 2023 22:19:08 +0300, Maxim Kochetkov wrote:
DMA mode uses hardware handshake signals. DMACR register is used to enable the DMA Controller interface operation. So add DMA enable/disable to i2s_start()/i2s_stop() functions if using DMA mode.
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/1] ASoC: dwc: add DMA handshake control commit: a42e988b6265dcd489feb1adab8551b40c988f43
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
-
Maxim Kochetkov