lkml.org 
[lkml]   [2011]   [Sep]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 17/17] ASoC: twl6040: Workaround for headset DC offset caused pop noise
    Date
    Both Headset DAC need to be enabled at the same time, before any of
    the output drivers are enabled.

    Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
    ---
    include/linux/mfd/twl6040.h | 1 +
    sound/soc/codecs/twl6040.c | 42 ++++++++++++++++++++++++++++++++++++++++--
    2 files changed, 41 insertions(+), 2 deletions(-)

    diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h
    index d9e05ea..0bbb1e7 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 abde625..063defc 100644
    --- a/sound/soc/codecs/twl6040.c
    +++ b/sound/soc/codecs/twl6040.c
    @@ -90,6 +90,7 @@ struct twl6040_data {
    int pll_power_mode;
    int hs_power_mode;
    int hs_power_mode_locked;
    + int hs_dac_enabled;
    unsigned int clk_in;
    unsigned int sysclk;
    u16 hs_left_step;
    @@ -660,6 +661,43 @@ 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;
    + struct twl6040_data *priv = snd_soc_codec_get_drvdata(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.
    + */
    + if (SND_SOC_DAPM_EVENT_ON(event)) {
    + if (!priv->hs_dac_enabled++) {
    + hslctl = twl6040_read_reg_cache(codec,
    + TWL6040_REG_HSLCTL);
    + hslctl |= TWL6040_HSDACENA;
    +
    + hsrctl = twl6040_read_reg_cache(codec,
    + TWL6040_REG_HSRCTL);
    + hsrctl |= TWL6040_HSDACENA;
    +
    + twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl);
    + twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl);
    + }
    + } else {
    + if (!--priv->hs_dac_enabled) {
    + hslctl = twl6040_read_reg_cache(codec,
    + TWL6040_REG_HSLCTL);
    + hslctl &= ~TWL6040_HSDACENA;
    +
    + hsrctl = twl6040_read_reg_cache(codec,
    + TWL6040_REG_HSRCTL);
    + hsrctl &= ~TWL6040_HSDACENA;
    +
    + twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl);
    + twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl);
    + }
    + }
    +
    msleep(1);
    return 0;
    }
    @@ -1146,11 +1184,11 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {

    /* DACs */
    SND_SOC_DAPM_DAC_E("HSDAC Left", "Headset Playback",
    - TWL6040_REG_HSLCTL, 0, 0,
    + SND_SOC_NOPM, 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,
    + SND_SOC_NOPM, 0, 0,
    twl6040_hs_dac_event,
    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
    SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback",
    --
    1.7.6.1


    \
     
     \ /
      Last update: 2011-09-15 14:45    [W:0.022 / U:61.060 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site