提交 c392bec7 编写于 作者: T Troy Kisky 提交者: Mark Brown

ASoC: DaVinci: i2s toggle clock to complete reset

Add toggle_clock function to complete i2s reset earlier.
Signed-off-by: NTroy Kisky <troy.kisky@boundarydevices.com>
Signed-off-by: NMark Brown <broonie@opensource.wolfsonmicro.com>
上级 35cf6358
...@@ -104,6 +104,7 @@ static struct davinci_pcm_dma_params davinci_i2s_pcm_in = { ...@@ -104,6 +104,7 @@ static struct davinci_pcm_dma_params davinci_i2s_pcm_in = {
struct davinci_mcbsp_dev { struct davinci_mcbsp_dev {
void __iomem *base; void __iomem *base;
u32 pcr;
struct clk *clk; struct clk *clk;
struct davinci_pcm_dma_params *dma_params[2]; struct davinci_pcm_dma_params *dma_params[2];
}; };
...@@ -119,17 +120,34 @@ static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg) ...@@ -119,17 +120,34 @@ static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg)
return __raw_readl(dev->base + reg); return __raw_readl(dev->base + reg);
} }
static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback)
{
u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP;
/* The clock needs to toggle to complete reset.
* So, fake it by toggling the clk polarity.
*/
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m);
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr);
}
static void davinci_mcbsp_start(struct snd_pcm_substream *substream) static void davinci_mcbsp_start(struct snd_pcm_substream *substream)
{ {
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_platform *platform = socdev->card->platform; struct snd_soc_platform *platform = socdev->card->platform;
int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
u32 spcr; u32 spcr;
int ret; int ret;
u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
/* Start the sample generator and enable transmitter/receiver */
spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
if (spcr & mask) {
/* start off disabled */
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
spcr & ~mask);
toggle_clock(dev, playback);
}
/* Start the sample generator and enable transmitter/receiver */
spcr |= DAVINCI_MCBSP_SPCR_GRST; spcr |= DAVINCI_MCBSP_SPCR_GRST;
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
...@@ -155,6 +173,7 @@ static void davinci_mcbsp_start(struct snd_pcm_substream *substream) ...@@ -155,6 +173,7 @@ static void davinci_mcbsp_start(struct snd_pcm_substream *substream)
spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
spcr &= ~DAVINCI_MCBSP_SPCR_XRST; spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
toggle_clock(dev, playback);
/* Restart the DMA */ /* Restart the DMA */
if (platform->pcm_ops->trigger) { if (platform->pcm_ops->trigger) {
...@@ -188,15 +207,14 @@ static void davinci_mcbsp_stop(struct snd_pcm_substream *substream) ...@@ -188,15 +207,14 @@ static void davinci_mcbsp_stop(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
u32 spcr; u32 spcr;
int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
/* Reset transmitter/receiver and sample rate/frame sync generators */ /* Reset transmitter/receiver and sample rate/frame sync generators */
spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST); spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST;
spcr &= ~DAVINCI_MCBSP_SPCR_XRST;
else
spcr &= ~DAVINCI_MCBSP_SPCR_RRST;
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);
toggle_clock(dev, playback);
} }
static int davinci_i2s_startup(struct snd_pcm_substream *substream, static int davinci_i2s_startup(struct snd_pcm_substream *substream,
...@@ -334,6 +352,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, ...@@ -334,6 +352,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
return -EINVAL; return -EINVAL;
} }
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
dev->pcr = pcr;
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr); davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册