Commit ae73b34f authored by Maxime Ripard's avatar Maxime Ripard Committed by Mark Brown

ASoC: sun4i-i2s: Implement capture support

The i2s driver was only implementing playback for now. Implement capture to
make sure that's not a limitation anymore.
Signed-off-by: default avatarMaxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 85915b63
...@@ -93,6 +93,7 @@ struct sun4i_i2s { ...@@ -93,6 +93,7 @@ struct sun4i_i2s {
struct clk *mod_clk; struct clk *mod_clk;
struct regmap *regmap; struct regmap *regmap;
struct snd_dmaengine_dai_dma_data capture_dma_data;
struct snd_dmaengine_dai_dma_data playback_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data;
}; };
...@@ -341,6 +342,27 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ...@@ -341,6 +342,27 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0; return 0;
} }
static void sun4i_i2s_start_capture(struct sun4i_i2s *i2s)
{
/* Flush RX FIFO */
regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
SUN4I_I2S_FIFO_CTRL_FLUSH_RX,
SUN4I_I2S_FIFO_CTRL_FLUSH_RX);
/* Clear RX counter */
regmap_write(i2s->regmap, SUN4I_I2S_RX_CNT_REG, 0);
/* Enable RX Block */
regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
SUN4I_I2S_CTRL_RX_EN,
SUN4I_I2S_CTRL_RX_EN);
/* Enable RX DRQ */
regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG,
SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN,
SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN);
}
static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s) static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s)
{ {
/* Flush TX FIFO */ /* Flush TX FIFO */
...@@ -362,6 +384,18 @@ static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s) ...@@ -362,6 +384,18 @@ static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s)
SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN); SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN);
} }
static void sun4i_i2s_stop_capture(struct sun4i_i2s *i2s)
{
/* Disable RX Block */
regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
SUN4I_I2S_CTRL_RX_EN,
0);
/* Disable RX DRQ */
regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG,
SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN,
0);
}
static void sun4i_i2s_stop_playback(struct sun4i_i2s *i2s) static void sun4i_i2s_stop_playback(struct sun4i_i2s *i2s)
{ {
...@@ -388,7 +422,7 @@ static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -388,7 +422,7 @@ static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
sun4i_i2s_start_playback(i2s); sun4i_i2s_start_playback(i2s);
else else
return -EINVAL; sun4i_i2s_start_capture(i2s);
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
...@@ -397,7 +431,7 @@ static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ...@@ -397,7 +431,7 @@ static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
sun4i_i2s_stop_playback(i2s); sun4i_i2s_stop_playback(i2s);
else else
return -EINVAL; sun4i_i2s_stop_capture(i2s);
break; break;
default: default:
...@@ -459,7 +493,9 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai) ...@@ -459,7 +493,9 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai)
{ {
struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, NULL); snd_soc_dai_init_dma_data(dai,
&i2s->playback_dma_data,
&i2s->capture_dma_data);
snd_soc_dai_set_drvdata(dai, i2s); snd_soc_dai_set_drvdata(dai, i2s);
...@@ -468,6 +504,13 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai) ...@@ -468,6 +504,13 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai)
static struct snd_soc_dai_driver sun4i_i2s_dai = { static struct snd_soc_dai_driver sun4i_i2s_dai = {
.probe = sun4i_i2s_dai_probe, .probe = sun4i_i2s_dai_probe,
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.playback = { .playback = {
.stream_name = "Playback", .stream_name = "Playback",
.channels_min = 2, .channels_min = 2,
...@@ -630,6 +673,9 @@ static int sun4i_i2s_probe(struct platform_device *pdev) ...@@ -630,6 +673,9 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG; i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG;
i2s->playback_dma_data.maxburst = 4; i2s->playback_dma_data.maxburst = 4;
i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG;
i2s->capture_dma_data.maxburst = 4;
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) { if (!pm_runtime_enabled(&pdev->dev)) {
ret = sun4i_i2s_runtime_resume(&pdev->dev); ret = sun4i_i2s_runtime_resume(&pdev->dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment