diff options
author | Misael Lopez Cruz <misael.lopez@ti.com> | 2012-03-06 12:11:34 -0600 |
---|---|---|
committer | Dmytro Kedrovskyi <x0169235@ti.com> | 2012-03-16 12:54:42 +0200 |
commit | c18a745af584df0ecfe2047a4fda53ae331f8a45 (patch) | |
tree | 7bed539f6571d167ce30137825400b0cca4f6bdb /sound/soc | |
parent | 9cfb7bccebf7b940068f4eef953359bfca4c905c (diff) | |
download | kernel_samsung_espresso10-c18a745af584df0ecfe2047a4fda53ae331f8a45.zip kernel_samsung_espresso10-c18a745af584df0ecfe2047a4fda53ae331f8a45.tar.gz kernel_samsung_espresso10-c18a745af584df0ecfe2047a4fda53ae331f8a45.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/soc')
-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 3f95ea2..98a5def 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -835,44 +835,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; } @@ -882,36 +868,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: @@ -919,7 +892,6 @@ static int twl6040_hs_dac_right_event(struct snd_soc_dapm_widget *w, } } - msleep(1); return 0; } @@ -1353,13 +1325,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_power_mode_event, |