diff options
author | Peter Ujfalusi <peter.ujfalusi@ti.com> | 2011-10-12 14:46:02 +0300 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-10-12 13:11:54 +0100 |
commit | 33b6816ca3a4027a1b5444c83c1c24c0b1991262 (patch) | |
tree | c14a30ad5b0d70023887f6de96889678409b8c2b | |
parent | 67c341302f5a401a405be758250bada39746c96b (diff) | |
download | op-kernel-dev-33b6816ca3a4027a1b5444c83c1c24c0b1991262.zip op-kernel-dev-33b6816ca3a4027a1b5444c83c1c24c0b1991262.tar.gz |
ASoC: twl6040: Workaround for headset DC offset caused pop noise
Both Headset DAC need to be turned on/off at the same time before
any of the output drivers are enabled (HS Left/Right, Earpiece).
Move the HS DAC enable code to sequenced DAPM_SUPPLY, and attach
it to the DACs.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | include/linux/mfd/twl6040.h | 1 | ||||
-rw-r--r-- | sound/soc/codecs/twl6040.c | 36 |
2 files changed, 29 insertions, 8 deletions
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h index 87a4778..2463c261 100644 --- a/include/linux/mfd/twl6040.h +++ b/include/linux/mfd/twl6040.h @@ -122,6 +122,7 @@ /* HSLCTL/R (0x10/0x11) fields */ +#define TWL6040_HSDACENA (1 << 0) #define TWL6040_HSDACMODE (1 << 1) #define TWL6040_HSDRVMODE (1 << 3) diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 8648498..6369230 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -654,6 +654,26 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf) static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { + struct snd_soc_codec *codec = w->codec; + u8 hslctl, hsrctl; + + /* + * Workaround for Headset DC offset caused pop noise: + * Both HS DAC need to be turned on (before the HS driver) and off at + * the same time. + */ + hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); + hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); + if (SND_SOC_DAPM_EVENT_ON(event)) { + hslctl |= TWL6040_HSDACENA; + hsrctl |= TWL6040_HSDACENA; + } else { + hslctl &= ~TWL6040_HSDACENA; + hsrctl &= ~TWL6040_HSDACENA; + } + twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl); + twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl); + msleep(1); return 0; } @@ -1103,14 +1123,8 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { TWL6040_REG_DMICBCTL, 4, 0), /* DACs */ - SND_SOC_DAPM_DAC_E("HSDAC Left", "Headset Playback", - TWL6040_REG_HSLCTL, 0, 0, - twl6040_hs_dac_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_DAC_E("HSDAC Right", "Headset Playback", - TWL6040_REG_HSRCTL, 0, 0, - twl6040_hs_dac_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback", SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback", TWL6040_REG_HFLCTL, 0, 0, twl6040_power_mode_event, @@ -1175,6 +1189,9 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { NULL, 0), SND_SOC_DAPM_SUPPLY("Vibra Right Control", TWL6040_REG_VIBCTLR, 2, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY_S("HSDAC Power", 1, SND_SOC_NOPM, 0, 0, + twl6040_hs_dac_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), /* Analog playback PGAs */ SND_SOC_DAPM_PGA("HF Left PGA", @@ -1204,6 +1221,9 @@ static const struct snd_soc_dapm_route intercon[] = { {"AFMAmpL", NULL, "AFML"}, {"AFMAmpR", NULL, "AFMR"}, + {"HSDAC Left", NULL, "HSDAC Power"}, + {"HSDAC Right", NULL, "HSDAC Power"}, + {"Headset Left Playback", "HS DAC", "HSDAC Left"}, {"Headset Left Playback", "Line-In amp", "AFMAmpL"}, |