diff options
-rw-r--r-- | arch/arm/plat-omap/include/mach/mcbsp.h | 4 | ||||
-rw-r--r-- | arch/arm/plat-omap/mcbsp.c | 50 | ||||
-rw-r--r-- | sound/soc/omap/omap-mcbsp.c | 10 |
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, | |||
387 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config); | 387 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config); |
388 | int omap_mcbsp_request(unsigned int id); | 388 | int omap_mcbsp_request(unsigned int id); |
389 | void omap_mcbsp_free(unsigned int id); | 389 | void omap_mcbsp_free(unsigned int id); |
390 | void omap_mcbsp_start(unsigned int id); | 390 | void omap_mcbsp_start(unsigned int id, int tx, int rx); |
391 | void omap_mcbsp_stop(unsigned int id); | 391 | void omap_mcbsp_stop(unsigned int id, int tx, int rx); |
392 | void omap_mcbsp_xmit_word(unsigned int id, u32 word); | 392 | void omap_mcbsp_xmit_word(unsigned int id, u32 word); |
393 | u32 omap_mcbsp_recv_word(unsigned int id); | 393 | u32 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) | |||
328 | EXPORT_SYMBOL(omap_mcbsp_free); | 328 | EXPORT_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 | */ |
335 | void omap_mcbsp_start(unsigned int id) | 335 | void 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 | } |
371 | EXPORT_SYMBOL(omap_mcbsp_start); | 379 | EXPORT_SYMBOL(omap_mcbsp_start); |
372 | 380 | ||
373 | void omap_mcbsp_stop(unsigned int id) | 381 | void 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 | } |
399 | EXPORT_SYMBOL(omap_mcbsp_stop); | 413 | EXPORT_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; |