mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-11 00:08:50 +00:00
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;
|
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,
|
static void i2s_start(struct dw_i2s_dev *dev,
|
||||||
struct snd_pcm_substream *substream)
|
struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct i2s_clk_config_data *config = &dev->config;
|
struct i2s_clk_config_data *config = &dev->config;
|
||||||
|
|
||||||
i2s_write_reg(dev->i2s_base, IER, 1);
|
i2s_write_reg(dev->i2s_base, IER, 1);
|
||||||
i2s_enable_irqs(dev, substream->stream, config->chan_nr);
|
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
i2s_write_reg(dev->i2s_base, ITER, 1);
|
i2s_write_reg(dev->i2s_base, ITER, 1);
|
||||||
else
|
else
|
||||||
i2s_write_reg(dev->i2s_base, IRER, 1);
|
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);
|
i2s_write_reg(dev->i2s_base, CER, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +208,10 @@ static void i2s_stop(struct dw_i2s_dev *dev,
|
|||||||
else
|
else
|
||||||
i2s_write_reg(dev->i2s_base, IRER, 0);
|
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) {
|
if (!dev->active) {
|
||||||
i2s_write_reg(dev->i2s_base, CER, 0);
|
i2s_write_reg(dev->i2s_base, CER, 0);
|
||||||
|
@ -53,6 +53,12 @@
|
|||||||
#define I2S_COMP_VERSION 0x01F8
|
#define I2S_COMP_VERSION 0x01F8
|
||||||
#define I2S_COMP_TYPE 0x01FC
|
#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
|
* Component parameter register fields - define the I2S block's
|
||||||
* configuration.
|
* configuration.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user