diff options
Diffstat (limited to 'sound/soc/ti/davinci-i2s.c')
-rw-r--r-- | sound/soc/ti/davinci-i2s.c | 90 |
1 files changed, 40 insertions, 50 deletions
diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index 92c1bdc69086..d89b5c928c4d 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -187,57 +187,9 @@ static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback) static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME); int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); u32 spcr; u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; - 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); - } - if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM | - DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) { - /* Start the sample generator */ - spcr |= DAVINCI_MCBSP_SPCR_GRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - } - - if (playback) { - /* Stop the DMA to avoid data loss */ - /* while the transmitter is out of reset to handle XSYNCERR */ - if (component->driver->ops->trigger) { - int ret = component->driver->ops->trigger(substream, - SNDRV_PCM_TRIGGER_STOP); - if (ret < 0) - printk(KERN_DEBUG "Playback DMA stop failed\n"); - } - - /* Enable the transmitter */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr |= DAVINCI_MCBSP_SPCR_XRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - - /* wait for any unexpected frame sync error to occur */ - udelay(100); - - /* Disable the transmitter to clear any outstanding XSYNCERR */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr &= ~DAVINCI_MCBSP_SPCR_XRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - toggle_clock(dev, playback); - - /* Restart the DMA */ - if (component->driver->ops->trigger) { - int ret = component->driver->ops->trigger(substream, - SNDRV_PCM_TRIGGER_START); - if (ret < 0) - printk(KERN_DEBUG "Playback DMA start failed\n"); - } - } /* Enable transmitter or receiver */ spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); @@ -575,7 +527,41 @@ static int davinci_i2s_prepare(struct snd_pcm_substream *substream, { struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + u32 spcr; + u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; + davinci_mcbsp_stop(dev, playback); + + 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); + } + if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM | + DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) { + /* Start the sample generator */ + spcr |= DAVINCI_MCBSP_SPCR_GRST; + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + } + + if (playback) { + /* Enable the transmitter */ + spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + spcr |= DAVINCI_MCBSP_SPCR_XRST; + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + + /* wait for any unexpected frame sync error to occur */ + udelay(100); + + /* Disable the transmitter to clear any outstanding XSYNCERR */ + spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + spcr &= ~DAVINCI_MCBSP_SPCR_XRST; + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + toggle_clock(dev, playback); + } + return 0; } @@ -612,6 +598,8 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, } #define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 +#define DAVINCI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) static const struct snd_soc_dai_ops davinci_i2s_dai_ops = { .shutdown = davinci_i2s_shutdown, @@ -639,12 +627,14 @@ static struct snd_soc_dai_driver davinci_i2s_dai = { .channels_min = 2, .channels_max = 2, .rates = DAVINCI_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .formats = DAVINCI_I2S_FORMATS, + }, .capture = { .channels_min = 2, .channels_max = 2, .rates = DAVINCI_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .formats = DAVINCI_I2S_FORMATS, + }, .ops = &davinci_i2s_dai_ops, }; |