aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-omap/include/mach/mcbsp.h4
-rw-r--r--arch/arm/plat-omap/mcbsp.c50
-rw-r--r--sound/soc/omap/omap-mcbsp.c10
3 files changed, 39 insertions, 25 deletions
diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h
index bb154ea76769..57249bb1e9bc 100644
--- a/arch/arm/plat-omap/include/mach/mcbsp.h
+++ b/arch/arm/plat-omap/include/mach/mcbsp.h
@@ -387,8 +387,8 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
387void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config); 387void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
388int omap_mcbsp_request(unsigned int id); 388int omap_mcbsp_request(unsigned int id);
389void omap_mcbsp_free(unsigned int id); 389void omap_mcbsp_free(unsigned int id);
390void omap_mcbsp_start(unsigned int id); 390void omap_mcbsp_start(unsigned int id, int tx, int rx);
391void omap_mcbsp_stop(unsigned int id); 391void omap_mcbsp_stop(unsigned int id, int tx, int rx);
392void omap_mcbsp_xmit_word(unsigned int id, u32 word); 392void omap_mcbsp_xmit_word(unsigned int id, u32 word);
393u32 omap_mcbsp_recv_word(unsigned int id); 393u32 omap_mcbsp_recv_word(unsigned int id);
394 394
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index efa0e0111f38..a3d2313460b3 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -328,14 +328,15 @@ void omap_mcbsp_free(unsigned int id)
328EXPORT_SYMBOL(omap_mcbsp_free); 328EXPORT_SYMBOL(omap_mcbsp_free);
329 329
330/* 330/*
331 * Here we start the McBSP, by enabling the sample 331 * Here we start the McBSP, by enabling transmitter, receiver or both.
332 * generator, both transmitter and receivers, 332 * If no transmitter or receiver is active prior calling, then sample-rate
333 * and the frame sync. 333 * generator and frame sync are started.
334 */ 334 */
335void omap_mcbsp_start(unsigned int id) 335void omap_mcbsp_start(unsigned int id, int tx, int rx)
336{ 336{
337 struct omap_mcbsp *mcbsp; 337 struct omap_mcbsp *mcbsp;
338 void __iomem *io_base; 338 void __iomem *io_base;
339 int idle;
339 u16 w; 340 u16 w;
340 341
341 if (!omap_mcbsp_check_valid_id(id)) { 342 if (!omap_mcbsp_check_valid_id(id)) {
@@ -348,32 +349,40 @@ void omap_mcbsp_start(unsigned int id)
348 mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; 349 mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7;
349 mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; 350 mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7;
350 351
351 /* Start the sample generator */ 352 idle = !((OMAP_MCBSP_READ(io_base, SPCR2) |
352 w = OMAP_MCBSP_READ(io_base, SPCR2); 353 OMAP_MCBSP_READ(io_base, SPCR1)) & 1);
353 OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6)); 354
355 if (idle) {
356 /* Start the sample generator */
357 w = OMAP_MCBSP_READ(io_base, SPCR2);
358 OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
359 }
354 360
355 /* Enable transmitter and receiver */ 361 /* Enable transmitter and receiver */
356 w = OMAP_MCBSP_READ(io_base, SPCR2); 362 w = OMAP_MCBSP_READ(io_base, SPCR2);
357 OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1); 363 OMAP_MCBSP_WRITE(io_base, SPCR2, w | (tx & 1));
358 364
359 w = OMAP_MCBSP_READ(io_base, SPCR1); 365 w = OMAP_MCBSP_READ(io_base, SPCR1);
360 OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1); 366 OMAP_MCBSP_WRITE(io_base, SPCR1, w | (rx & 1));
361 367
362 udelay(100); 368 udelay(100);
363 369
364 /* Start frame sync */ 370 if (idle) {
365 w = OMAP_MCBSP_READ(io_base, SPCR2); 371 /* Start frame sync */
366 OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7)); 372 w = OMAP_MCBSP_READ(io_base, SPCR2);
373 OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
374 }
367 375
368 /* Dump McBSP Regs */ 376 /* Dump McBSP Regs */
369 omap_mcbsp_dump_reg(id); 377 omap_mcbsp_dump_reg(id);
370} 378}
371EXPORT_SYMBOL(omap_mcbsp_start); 379EXPORT_SYMBOL(omap_mcbsp_start);
372 380
373void omap_mcbsp_stop(unsigned int id) 381void omap_mcbsp_stop(unsigned int id, int tx, int rx)
374{ 382{
375 struct omap_mcbsp *mcbsp; 383 struct omap_mcbsp *mcbsp;
376 void __iomem *io_base; 384 void __iomem *io_base;
385 int idle;
377 u16 w; 386 u16 w;
378 387
379 if (!omap_mcbsp_check_valid_id(id)) { 388 if (!omap_mcbsp_check_valid_id(id)) {
@@ -386,15 +395,20 @@ void omap_mcbsp_stop(unsigned int id)
386 395
387 /* Reset transmitter */ 396 /* Reset transmitter */
388 w = OMAP_MCBSP_READ(io_base, SPCR2); 397 w = OMAP_MCBSP_READ(io_base, SPCR2);
389 OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1)); 398 OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(tx & 1));
390 399
391 /* Reset receiver */ 400 /* Reset receiver */
392 w = OMAP_MCBSP_READ(io_base, SPCR1); 401 w = OMAP_MCBSP_READ(io_base, SPCR1);
393 OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1)); 402 OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(rx & 1));
394 403
395 /* Reset the sample rate generator */ 404 idle = !((OMAP_MCBSP_READ(io_base, SPCR2) |
396 w = OMAP_MCBSP_READ(io_base, SPCR2); 405 OMAP_MCBSP_READ(io_base, SPCR1)) & 1);
397 OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); 406
407 if (idle) {
408 /* Reset the sample rate generator */
409 w = OMAP_MCBSP_READ(io_base, SPCR2);
410 OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
411 }
398} 412}
399EXPORT_SYMBOL(omap_mcbsp_stop); 413EXPORT_SYMBOL(omap_mcbsp_stop);
400 414
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index a5d46a7b196a..6a837ffd5d0b 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -183,21 +183,21 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
183 struct snd_soc_pcm_runtime *rtd = substream->private_data; 183 struct snd_soc_pcm_runtime *rtd = substream->private_data;
184 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 184 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
185 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 185 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
186 int err = 0; 186 int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
187 187
188 switch (cmd) { 188 switch (cmd) {
189 case SNDRV_PCM_TRIGGER_START: 189 case SNDRV_PCM_TRIGGER_START:
190 case SNDRV_PCM_TRIGGER_RESUME: 190 case SNDRV_PCM_TRIGGER_RESUME:
191 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 191 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
192 if (!mcbsp_data->active++) 192 mcbsp_data->active++;
193 omap_mcbsp_start(mcbsp_data->bus_id); 193 omap_mcbsp_start(mcbsp_data->bus_id, play, !play);
194 break; 194 break;
195 195
196 case SNDRV_PCM_TRIGGER_STOP: 196 case SNDRV_PCM_TRIGGER_STOP:
197 case SNDRV_PCM_TRIGGER_SUSPEND: 197 case SNDRV_PCM_TRIGGER_SUSPEND:
198 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 198 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
199 if (!--mcbsp_data->active) 199 omap_mcbsp_stop(mcbsp_data->bus_id, play, !play);
200 omap_mcbsp_stop(mcbsp_data->bus_id); 200 mcbsp_data->active--;
201 break; 201 break;
202 default: 202 default:
203 err = -EINVAL; 203 err = -EINVAL;