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:
parent
02474880e8
commit
a42e988b62
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue