@ -104,6 +104,7 @@ static struct davinci_pcm_dma_params davinci_i2s_pcm_in = {
struct davinci_mcbsp_dev {
void __iomem * base ;
u32 pcr ;
struct clk * clk ;
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)
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 )
{
struct snd_soc_pcm_runtime * rtd = substream - > private_data ;
struct davinci_mcbsp_dev * dev = rtd - > dai - > cpu_dai - > private_data ;
struct snd_soc_device * socdev = rtd - > socdev ;
struct snd_soc_platform * platform = socdev - > card - > platform ;
int playback = ( substream - > stream = = SNDRV_PCM_STREAM_PLAYBACK ) ;
u32 spcr ;
int ret ;
/* Start the sample generator and enable transmitter/receiver */
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 ) ;
}
/* Start the sample generator and enable transmitter/receiver */
spcr | = DAVINCI_MCBSP_SPCR_GRST ;
davinci_mcbsp_write_reg ( dev , DAVINCI_MCBSP_SPCR_REG , spcr ) ;
@ -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_SPCR_XRST ;
davinci_mcbsp_write_reg ( dev , DAVINCI_MCBSP_SPCR_REG , spcr ) ;
toggle_clock ( dev , playback ) ;
/* Restart the DMA */
if ( platform - > pcm_ops - > trigger ) {
@ -188,15 +207,14 @@ static void davinci_mcbsp_stop(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime * rtd = substream - > private_data ;
struct davinci_mcbsp_dev * dev = rtd - > dai - > cpu_dai - > private_data ;
u32 spcr ;
int playback = ( substream - > stream = = SNDRV_PCM_STREAM_PLAYBACK ) ;
/* Reset transmitter/receiver and sample rate/frame sync generators */
spcr = davinci_mcbsp_read_reg ( dev , DAVINCI_MCBSP_SPCR_REG ) ;
spcr & = ~ ( DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST ) ;
if ( substream - > stream = = SNDRV_PCM_STREAM_PLAYBACK )
spcr & = ~ DAVINCI_MCBSP_SPCR_XRST ;
else
spcr & = ~ DAVINCI_MCBSP_SPCR_RRST ;
spcr & = playback ? ~ DAVINCI_MCBSP_SPCR_XRST : ~ DAVINCI_MCBSP_SPCR_RRST ;
davinci_mcbsp_write_reg ( dev , DAVINCI_MCBSP_SPCR_REG , spcr ) ;
toggle_clock ( dev , playback ) ;
}
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,
return - EINVAL ;
}
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_RCR_REG , rcr ) ;
davinci_mcbsp_write_reg ( dev , DAVINCI_MCBSP_XCR_REG , xcr ) ;