This patch fixes the - agressive - 'tuck' sound heard when the codec goes to standby mode.
We need to wait for the ramp down completion in case of headsetl_event:POST_PMD.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@nokia.com --- sound/soc/codecs/twl4030.c | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index fd392c6..c22f8d6 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c @@ -130,6 +130,8 @@ struct twl4030_priv { unsigned int rate; unsigned int sample_bits; unsigned int channels; + + unsigned int sysclk; };
/* @@ -586,6 +588,11 @@ static int headsetl_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { unsigned char hs_gain, hs_pop; + struct twl4030_priv *twl4030 = w->codec->private_data; + /* Base values for ramp delay calculation: 2^19 - 2^26 */ + unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304, + 8388608, 16777216, 33554432, 67108864}; + unsigned int ramp_delay;
/* Save the current volume */ hs_gain = twl4030_read_reg_cache(w->codec, TWL4030_REG_HS_GAIN_SET); @@ -609,6 +616,12 @@ static int headsetl_event(struct snd_soc_dapm_widget *w, /* Do the anti-pop/bias ramp disable according to the TRM */ hs_pop &= ~TWL4030_RAMP_EN; twl4030_write(w->codec, TWL4030_REG_HS_POPN_SET, hs_pop); + + /* We need to wait RAMP_DELAY time, otherwise 'tuck' sound can + * be heard on the output */ + ramp_delay = (hs_pop & TWL4030_RAMP_DELAY) >> 2; + mdelay(ramp_base[ramp_delay] / twl4030->sysclk); + /* Bypass the reg_cache to mute the headset */ twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, hs_gain & (~0x0f), @@ -1567,17 +1580,21 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir) { struct snd_soc_codec *codec = codec_dai->codec; + struct twl4030_priv *twl4030 = codec->private_data; u8 infreq;
switch (freq) { case 19200000: infreq = TWL4030_APLL_INFREQ_19200KHZ; + twl4030->sysclk = 19200; break; case 26000000: infreq = TWL4030_APLL_INFREQ_26000KHZ; + twl4030->sysclk = 26000; break; case 38400000: infreq = TWL4030_APLL_INFREQ_38400KHZ; + twl4030->sysclk = 38400; break; default: printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n", @@ -1929,6 +1946,9 @@ static int twl4030_probe(struct platform_device *pdev) kfree(codec); return -ENOMEM; } + /* Set default sysclk (used by the headsetl_event callback for + * pop-attenuation) */ + twl4030->sysclk = 26000;
codec->private_data = twl4030; socdev->card->codec = codec;