diff options
author | Misael Lopez Cruz <misael.lopez@ti.com> | 2012-03-06 12:11:34 -0600 |
---|---|---|
committer | Ziyann <jaraidaniel@gmail.com> | 2014-10-03 01:18:01 +0200 |
commit | 80013f268131a333cbbf00354a0691543722d426 (patch) | |
tree | a67308b98500f1e456188d7ac24c36ffd328da39 /sound | |
parent | d40b8dc7c1928866ea9ab2bd4a0b71347b43aafa (diff) | |
download | kernel_samsung_tuna-80013f268131a333cbbf00354a0691543722d426.zip kernel_samsung_tuna-80013f268131a333cbbf00354a0691543722d426.tar.gz kernel_samsung_tuna-80013f268131a333cbbf00354a0691543722d426.tar.bz2 |
ASoC: twl6040: Fix HS DACs DC offset errata
Current implementation of HSDACs DC offset errata disables DACR when
headset and earpiece outputs are used simultaneously. A simpler approach
is used:
- Headset DAC Left:
o HSDACR must be enabled before enabling HSDACL, since HSDACL reset is
done when HSDACR is enabled
o No additional handling required for power-down
- Headset DAC Right:
o No special handling required for power-up
o HSDACR reset is done when HSDACL is enabled, so in case DACL was
already disabled, re-enabled it momentarily while HSDACR power-down
occurs.
Change-Id: I20f29602268d701b64c10dfa86cc43f66b8325b0
Signed-off-by: Misael Lopez Cruz <misael.lopez@ti.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/twl6040.c | 72 |
1 files changed, 22 insertions, 50 deletions
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index f03d6d1..55f515a 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -804,44 +804,30 @@ static int twl6040_hs_dac_left_event(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = w->codec; struct twl6040 *twl6040 = codec->control_data; - int hsrctl, earpiece_on; + int hsrctl; /* SW Workaround for DC Offset On EAR Differential Output Errata */ if (twl6040_get_icrev(twl6040) < TWL6040_REV_1_3) { hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); - earpiece_on = twl6040_read_reg_cache(codec, TWL6040_REG_EARCTL) - & TWL6040_EARENA; switch (event) { case SND_SOC_DAPM_PRE_PMU: - if (!(hsrctl & TWL6040_HSDACENAR)) - twl6040_write(codec, TWL6040_REG_HSRCTL, - hsrctl | TWL6040_HSDACENAR); + /* HSDACL reset is done when HSDACR is enabled */ + twl6040_reg_write(twl6040, TWL6040_REG_HSRCTL, + hsrctl | TWL6040_HSDACENAR); break; - - case SND_SOC_DAPM_PRE_PMD: - if (!(hsrctl & TWL6040_HSDACENAR)) - twl6040_write(codec, TWL6040_REG_HSRCTL, - hsrctl | TWL6040_HSDACENAR); - break; - case SND_SOC_DAPM_POST_PMU: - if ((hsrctl & TWL6040_HSDACENAR) || earpiece_on) - twl6040_write(codec, TWL6040_REG_HSRCTL, - hsrctl & ~TWL6040_HSDACENAR); - break; - + /* Sync HSDACR with reg cache */ + twl6040_reg_write(twl6040, TWL6040_REG_HSRCTL, hsrctl); + /* Fall through */ case SND_SOC_DAPM_POST_PMD: - if (hsrctl & TWL6040_HSDACENAR) - twl6040_write(codec, TWL6040_REG_HSRCTL, - hsrctl & ~TWL6040_HSDACENAR); + /* HSDAC settling time */ + usleep_range(80, 200); break; - default: break; } } - msleep(1); return 0; } @@ -851,36 +837,23 @@ static int twl6040_hs_dac_right_event(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = w->codec; struct twl6040 *twl6040 = codec->control_data; int hslctl; - int earpiece_on; /* SW Workaround for DC Offset On EAR Differential Output Errata */ if (twl6040_get_icrev(twl6040) < TWL6040_REV_1_3) { hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); - earpiece_on = twl6040_read_reg_cache(codec, TWL6040_REG_EARCTL) - & TWL6040_EARENA; switch (event) { - case SND_SOC_DAPM_PRE_PMU: - if (!(hslctl & TWL6040_HSDACENAL)) - twl6040_write(codec, TWL6040_REG_HSLCTL, - hslctl | TWL6040_HSDACENAL); - break; - case SND_SOC_DAPM_PRE_PMD: - if (!(hslctl & TWL6040_HSDACENAL)) - twl6040_write(codec, TWL6040_REG_HSLCTL, - hslctl | TWL6040_HSDACENAL); + /* HSDACR reset is done when HSDACL is enabled */ + twl6040_reg_write(twl6040, TWL6040_REG_HSLCTL, + hslctl | TWL6040_HSDACENAL); break; - - case SND_SOC_DAPM_POST_PMU: - if ((hslctl & TWL6040_HSDACENAL) && earpiece_on) - twl6040_write(codec, TWL6040_REG_HSLCTL, - hslctl & ~TWL6040_HSDACENAL); - break; - case SND_SOC_DAPM_POST_PMD: - if (hslctl & TWL6040_HSDACENAL) - twl6040_write(codec, TWL6040_REG_HSLCTL, - hslctl & ~TWL6040_HSDACENAL); + /* Sync HSDACL with reg cache */ + twl6040_reg_write(twl6040, TWL6040_REG_HSLCTL, hslctl); + /* Fall through */ + case SND_SOC_DAPM_POST_PMU: + /* HSDAC settling time */ + usleep_range(80, 200); break; default: @@ -888,7 +861,6 @@ static int twl6040_hs_dac_right_event(struct snd_soc_dapm_widget *w, } } - msleep(1); return 0; } @@ -1312,13 +1284,13 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { SND_SOC_DAPM_DAC_E("HSDAC Left", "Headset Playback", TWL6040_REG_HSLCTL, 0, 0, twl6040_hs_dac_left_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD | - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PRE_PMU | 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_right_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD | - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback", TWL6040_REG_HFLCTL, 0, 0, twl6040_dac_event, |