aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/davinci/davinci-mcasp.c')
-rw-r--r--sound/soc/davinci/davinci-mcasp.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index b215c0b2ae50..6ec241335cc3 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -348,8 +348,24 @@ static inline void mcasp_set_ctl_reg(void __iomem *regs, u32 val)
348 348
349static void mcasp_start_rx(struct davinci_audio_dev *dev) 349static void mcasp_start_rx(struct davinci_audio_dev *dev)
350{ 350{
351 u32 rxfmctl = mcasp_get_reg(dev->base + DAVINCI_MCASP_RXFMCTL_REG);
352
351 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); 353 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
352 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); 354 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
355
356 /*
357 * Enable TX FSG when McASP is in sync mode and is master since the
358 * TX section provides FSYNC for RX too. TX clk dividers are also
359 * enabled for cases where ACLKR pin is not connected (typically
360 * done when AFSR is not used either)
361 */
362 if (rxfmctl & AFSRE) {
363 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG,
364 TXHCLKRST);
365 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG,
366 TXCLKRST);
367 }
368
353 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); 369 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR);
354 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); 370 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0);
355 371
@@ -359,6 +375,10 @@ static void mcasp_start_rx(struct davinci_audio_dev *dev)
359 375
360 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); 376 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
361 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); 377 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
378
379 if (rxfmctl & AFSRE)
380 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG,
381 TXFSRST);
362} 382}
363 383
364static void mcasp_start_tx(struct davinci_audio_dev *dev) 384static void mcasp_start_tx(struct davinci_audio_dev *dev)
@@ -431,13 +451,28 @@ static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream)
431 451
432static void mcasp_stop_rx(struct davinci_audio_dev *dev) 452static void mcasp_stop_rx(struct davinci_audio_dev *dev)
433{ 453{
454 u32 gblctl = mcasp_get_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG);
455 u32 rxfmctl = mcasp_get_reg(dev->base + DAVINCI_MCASP_RXFMCTL_REG);
456
457 /* Disable TX FSG if RX was the only active user */
458 if ((rxfmctl & AFSRE) && !(gblctl & TXSMRST))
459 mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0);
460
434 mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0); 461 mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0);
435 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); 462 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
436} 463}
437 464
438static void mcasp_stop_tx(struct davinci_audio_dev *dev) 465static void mcasp_stop_tx(struct davinci_audio_dev *dev)
439{ 466{
440 mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0); 467 u32 gblctl = mcasp_get_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG);
468 u32 rxfmctl = mcasp_get_reg(dev->base + DAVINCI_MCASP_RXFMCTL_REG);
469 u32 val = 0;
470
471 /* Keep FSG active until RX section is stopped too */
472 if ((rxfmctl & AFSRE) && (gblctl & RXSMRST))
473 val = TXHCLKRST | TXCLKRST | TXFSRST;
474
475 mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, val);
441 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); 476 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
442} 477}
443 478