diff options
Diffstat (limited to 'sound/soc/omap/omap-mcbsp.c')
-rw-r--r-- | sound/soc/omap/omap-mcbsp.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 6e855080e6ea..580de5a8dba6 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -139,28 +139,59 @@ static const unsigned long omap34xx_mcbsp_port[][2] = { | |||
139 | static const unsigned long omap34xx_mcbsp_port[][2] = {}; | 139 | static const unsigned long omap34xx_mcbsp_port[][2] = {}; |
140 | #endif | 140 | #endif |
141 | 141 | ||
142 | static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) | ||
143 | { | ||
144 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
145 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
146 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | ||
147 | int samples = snd_pcm_lib_period_bytes(substream) >> 1; | ||
148 | |||
149 | /* Configure McBSP internal buffer usage */ | ||
150 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
151 | omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, samples - 1); | ||
152 | else | ||
153 | omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, samples - 1); | ||
154 | } | ||
155 | |||
142 | static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, | 156 | static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, |
143 | struct snd_soc_dai *dai) | 157 | struct snd_soc_dai *dai) |
144 | { | 158 | { |
145 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 159 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
146 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 160 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
147 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | 161 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); |
162 | int bus_id = mcbsp_data->bus_id; | ||
148 | int err = 0; | 163 | int err = 0; |
149 | 164 | ||
150 | if (cpu_is_omap343x() && mcbsp_data->bus_id == 1) { | 165 | if (!cpu_dai->active) |
166 | err = omap_mcbsp_request(bus_id); | ||
167 | |||
168 | if (cpu_is_omap343x()) { | ||
169 | int max_period; | ||
170 | |||
151 | /* | 171 | /* |
152 | * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer. | 172 | * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer. |
153 | * Set constraint for minimum buffer size to the same than FIFO | 173 | * Set constraint for minimum buffer size to the same than FIFO |
154 | * size in order to avoid underruns in playback startup because | 174 | * size in order to avoid underruns in playback startup because |
155 | * HW is keeping the DMA request active until FIFO is filled. | 175 | * HW is keeping the DMA request active until FIFO is filled. |
156 | */ | 176 | */ |
177 | if (bus_id == 1) | ||
178 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
179 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | ||
180 | 4096, UINT_MAX); | ||
181 | |||
182 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
183 | max_period = omap_mcbsp_get_max_tx_threshold(bus_id); | ||
184 | else | ||
185 | max_period = omap_mcbsp_get_max_rx_threshold(bus_id); | ||
186 | |||
187 | max_period++; | ||
188 | max_period <<= 1; | ||
189 | |||
157 | snd_pcm_hw_constraint_minmax(substream->runtime, | 190 | snd_pcm_hw_constraint_minmax(substream->runtime, |
158 | SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4096, UINT_MAX); | 191 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, |
192 | 32, max_period); | ||
159 | } | 193 | } |
160 | 194 | ||
161 | if (!cpu_dai->active) | ||
162 | err = omap_mcbsp_request(mcbsp_data->bus_id); | ||
163 | |||
164 | return err; | 195 | return err; |
165 | } | 196 | } |
166 | 197 | ||
@@ -220,7 +251,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
220 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | 251 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); |
221 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; | 252 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; |
222 | int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; | 253 | int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; |
223 | int wlen, channels, wpf; | 254 | int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; |
224 | unsigned long port; | 255 | unsigned long port; |
225 | unsigned int format; | 256 | unsigned int format; |
226 | 257 | ||
@@ -236,6 +267,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
236 | } else if (cpu_is_omap343x()) { | 267 | } else if (cpu_is_omap343x()) { |
237 | dma = omap24xx_dma_reqs[bus_id][substream->stream]; | 268 | dma = omap24xx_dma_reqs[bus_id][substream->stream]; |
238 | port = omap34xx_mcbsp_port[bus_id][substream->stream]; | 269 | port = omap34xx_mcbsp_port[bus_id][substream->stream]; |
270 | omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold = | ||
271 | omap_mcbsp_set_threshold; | ||
272 | sync_mode = OMAP_DMA_SYNC_FRAME; | ||
239 | } else { | 273 | } else { |
240 | return -ENODEV; | 274 | return -ENODEV; |
241 | } | 275 | } |
@@ -243,6 +277,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
243 | substream->stream ? "Audio Capture" : "Audio Playback"; | 277 | substream->stream ? "Audio Capture" : "Audio Playback"; |
244 | omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; | 278 | omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; |
245 | omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; | 279 | omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; |
280 | omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode; | ||
246 | cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; | 281 | cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; |
247 | 282 | ||
248 | if (mcbsp_data->configured) { | 283 | if (mcbsp_data->configured) { |