diff options
author | Misael Lopez Cruz | 2013-08-08 01:23:07 -0500 |
---|---|---|
committer | Misael Lopez Cruz | 2013-08-08 01:36:52 -0500 |
commit | 5f00ae3ddba3ad66200c8e1eaf78399018bf7618 (patch) | |
tree | 8150bb15e85bf724f509872e07ed23fdfaffda65 | |
parent | b8e46f23e78fb2b804e5222590fbd90df340b114 (diff) | |
download | kernel-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.c | 22 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-mcasp.h | 1 |
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; |