aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorMisael Lopez Cruz <misael.lopez@ti.com>2012-03-06 12:11:34 -0600
committerZiyann <jaraidaniel@gmail.com>2014-10-03 01:18:01 +0200
commit80013f268131a333cbbf00354a0691543722d426 (patch)
treea67308b98500f1e456188d7ac24c36ffd328da39 /sound
parentd40b8dc7c1928866ea9ab2bd4a0b71347b43aafa (diff)
downloadkernel_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.c72
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,