aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMisael Lopez Cruz2013-08-08 01:23:07 -0500
committerMisael Lopez Cruz2013-08-08 01:36:52 -0500
commit5f00ae3ddba3ad66200c8e1eaf78399018bf7618 (patch)
tree8150bb15e85bf724f509872e07ed23fdfaffda65
parentb8e46f23e78fb2b804e5222590fbd90df340b114 (diff)
downloadkernel-audio-5f00ae3ddba3ad66200c8e1eaf78399018bf7618.tar.gz
kernel-audio-5f00ae3ddba3ad66200c8e1eaf78399018bf7618.tar.xz
kernel-audio-5f00ae3ddba3ad66200c8e1eaf78399018bf7618.zip
ASoC: davinci-mcasp: Mute transmit data during stop
Reset of the state machine, serializer and frame sync generator can occur in the middle of a slot, making the transmit pin go to its inactive state. It can cause discontinuities that may lead to glitches. The discontinuities can be more abrupt for audio samples with negative values. Muting the transmit data by masking out all its bits can prevent this problem. A delay is required to ensure at least one slot uses the new bit mask, the worst case (longest slot) is for 8kHz, mono (125 us). Change-Id: I812ac674d1c9a3905086a966e0ec4795374f333a Signed-off-by: Misael Lopez Cruz <misael.lopez@ti.com>
-rw-r--r--sound/soc/davinci/davinci-mcasp.c22
-rw-r--r--sound/soc/davinci/davinci-mcasp.h1
2 files changed, 19 insertions, 4 deletions
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index ef30dbdd7aee..e0048d1ed7ce 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -394,6 +394,8 @@ static void mcasp_start_tx(struct davinci_audio_dev *dev)
394 u8 offset = 0, i; 394 u8 offset = 0, i;
395 u32 cnt; 395 u32 cnt;
396 396
397 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, dev->bit_mask);
398
397 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); 399 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
398 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); 400 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
399 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); 401 mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR);
@@ -505,6 +507,19 @@ static void mcasp_stop_tx(struct davinci_audio_dev *dev)
505 if ((rxfmctl & AFSRE) && (gblctl & RXSMRST)) 507 if ((rxfmctl & AFSRE) && (gblctl & RXSMRST))
506 val = TXHCLKRST | TXCLKRST | TXFSRST; 508 val = TXHCLKRST | TXCLKRST | TXFSRST;
507 509
510 /*
511 * Reset of the state machine, serializer and frame sync generator
512 * can occur in the middle of a slot which can cause discontinuities
513 * that may lead to glitches. It can be prevented muting the transmit
514 * data by masking out all its bits.
515 * A delay is required to ensure at least one slot uses the new TXMASK,
516 * the worst case (longest slot) is for 8kHz, mono (125 us).
517 * Implementation has to use udelay since it's executed in atomic
518 * context (trigger() callback).
519 */
520 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0);
521 udelay(125);
522
508 mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, val); 523 mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, val);
509 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); 524 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
510} 525}
@@ -703,9 +718,10 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
703 u32 fmt; 718 u32 fmt;
704 u32 tx_rotate = (word_length / 4) & 0x7; 719 u32 tx_rotate = (word_length / 4) & 0x7;
705 u32 rx_rotate; 720 u32 rx_rotate;
706 u32 mask = (1ULL << word_length) - 1;
707 u32 slot_length; 721 u32 slot_length;
708 722
723 dev->bit_mask = (1ULL << word_length) - 1;
724
709 /* 725 /*
710 * if s BCLK-to-LRCLK ratio has been configured via the set_clkdiv() 726 * if s BCLK-to-LRCLK ratio has been configured via the set_clkdiv()
711 * callback, take it into account here. That allows us to for example 727 * callback, take it into account here. That allows us to for example
@@ -735,11 +751,9 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
735 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, 751 mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
736 RXROT(rx_rotate), RXROT(7)); 752 RXROT(rx_rotate), RXROT(7));
737 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, 753 mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG,
738 mask); 754 dev->bit_mask);
739 } 755 }
740 756
741 mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask);
742
743 return 0; 757 return 0;
744} 758}
745 759
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index 48784954c83c..b541a8de773f 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -39,6 +39,7 @@ struct davinci_audio_dev {
39 u8 *serial_dir; 39 u8 *serial_dir;
40 u32 tx_dismod; 40 u32 tx_dismod;
41 u32 rx_dismod; 41 u32 rx_dismod;
42 u32 bit_mask;
42 u8 version; 43 u8 version;
43 u16 bclk_lrclk_ratio; 44 u16 bclk_lrclk_ratio;
44 unsigned int channels; 45 unsigned int channels;