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>
Link: https://lore.kernel.org/r/20230613191910.725049-1-fido_max@inbox.ru
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Maxim Kochetkov 2023-06-13 22:19:08 +03:00 committed by Mark Brown
parent 02474880e8
commit a42e988b62
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
2 changed files with 43 additions and 2 deletions

View File

@ -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);

View File

@ -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.