diff options
Diffstat (limited to 'sound/soc/davinci/davinci-i2s.c')
-rw-r--r-- | sound/soc/davinci/davinci-i2s.c | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index d814ec8947e5..8c1bf876031d 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c | |||
@@ -111,16 +111,59 @@ static void davinci_mcbsp_start(struct snd_pcm_substream *substream) | |||
111 | { | 111 | { |
112 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 112 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
113 | struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; | 113 | struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; |
114 | struct snd_soc_device *socdev = rtd->socdev; | ||
115 | struct snd_soc_platform *platform = socdev->platform; | ||
114 | u32 w; | 116 | u32 w; |
117 | int ret; | ||
115 | 118 | ||
116 | /* Start the sample generator and enable transmitter/receiver */ | 119 | /* Start the sample generator and enable transmitter/receiver */ |
117 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | 120 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); |
118 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1); | 121 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1); |
119 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 122 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); |
123 | |||
124 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
125 | /* Stop the DMA to avoid data loss */ | ||
126 | /* while the transmitter is out of reset to handle XSYNCERR */ | ||
127 | if (platform->pcm_ops->trigger) { | ||
128 | ret = platform->pcm_ops->trigger(substream, | ||
129 | SNDRV_PCM_TRIGGER_STOP); | ||
130 | if (ret < 0) | ||
131 | printk(KERN_DEBUG "Playback DMA stop failed\n"); | ||
132 | } | ||
133 | |||
134 | /* Enable the transmitter */ | ||
135 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | ||
120 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); | 136 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); |
121 | else | 137 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); |
138 | |||
139 | /* wait for any unexpected frame sync error to occur */ | ||
140 | udelay(100); | ||
141 | |||
142 | /* Disable the transmitter to clear any outstanding XSYNCERR */ | ||
143 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | ||
144 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0); | ||
145 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); | ||
146 | |||
147 | /* Restart the DMA */ | ||
148 | if (platform->pcm_ops->trigger) { | ||
149 | ret = platform->pcm_ops->trigger(substream, | ||
150 | SNDRV_PCM_TRIGGER_START); | ||
151 | if (ret < 0) | ||
152 | printk(KERN_DEBUG "Playback DMA start failed\n"); | ||
153 | } | ||
154 | /* Enable the transmitter */ | ||
155 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | ||
156 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); | ||
157 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); | ||
158 | |||
159 | } else { | ||
160 | |||
161 | /* Enable the reciever */ | ||
162 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | ||
122 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1); | 163 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1); |
123 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); | 164 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); |
165 | } | ||
166 | |||
124 | 167 | ||
125 | /* Start frame sync */ | 168 | /* Start frame sync */ |
126 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | 169 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); |