Commit 5a2e9a48 authored by Peter Ujfalusi's avatar Peter Ujfalusi Committed by Mark Brown

ASoC: TWL4030: Handsfree pop removal redesign

Move the HandsfreeL/R (IHFL/R) pop removal code from the DAPM_MUX_E
to a more appropriate DAPM_PGA_E widget.
Also fix the power-up sequence to match with the TRM.
The power-down sequence is not described in the TRM, so do it
in a way, which seams like the correct sequence.
Signed-off-by: default avatarPeter Ujfalusi <peter.ujfalusi@nokia.com>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 0bc53a67
...@@ -546,27 +546,61 @@ static int micpath_event(struct snd_soc_dapm_widget *w, ...@@ -546,27 +546,61 @@ static int micpath_event(struct snd_soc_dapm_widget *w,
return 0; return 0;
} }
static int handsfree_event(struct snd_soc_dapm_widget *w, static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp)
struct snd_kcontrol *kcontrol, int event)
{ {
struct soc_enum *e = (struct soc_enum *)w->kcontrols->private_value;
unsigned char hs_ctl; unsigned char hs_ctl;
hs_ctl = twl4030_read_reg_cache(w->codec, e->reg); hs_ctl = twl4030_read_reg_cache(codec, reg);
if (hs_ctl & TWL4030_HF_CTL_REF_EN) { if (ramp) {
/* HF ramp-up */
hs_ctl |= TWL4030_HF_CTL_REF_EN;
twl4030_write(codec, reg, hs_ctl);
udelay(10);
hs_ctl |= TWL4030_HF_CTL_RAMP_EN; hs_ctl |= TWL4030_HF_CTL_RAMP_EN;
twl4030_write(w->codec, e->reg, hs_ctl); twl4030_write(codec, reg, hs_ctl);
udelay(40);
hs_ctl |= TWL4030_HF_CTL_LOOP_EN; hs_ctl |= TWL4030_HF_CTL_LOOP_EN;
twl4030_write(w->codec, e->reg, hs_ctl);
hs_ctl |= TWL4030_HF_CTL_HB_EN; hs_ctl |= TWL4030_HF_CTL_HB_EN;
twl4030_write(w->codec, e->reg, hs_ctl); twl4030_write(codec, reg, hs_ctl);
} else { } else {
hs_ctl &= ~(TWL4030_HF_CTL_RAMP_EN | TWL4030_HF_CTL_LOOP_EN /* HF ramp-down */
| TWL4030_HF_CTL_HB_EN); hs_ctl &= ~TWL4030_HF_CTL_LOOP_EN;
twl4030_write(w->codec, e->reg, hs_ctl); hs_ctl &= ~TWL4030_HF_CTL_HB_EN;
twl4030_write(codec, reg, hs_ctl);
hs_ctl &= ~TWL4030_HF_CTL_RAMP_EN;
twl4030_write(codec, reg, hs_ctl);
udelay(40);
hs_ctl &= ~TWL4030_HF_CTL_REF_EN;
twl4030_write(codec, reg, hs_ctl);
}
}
static int handsfreelpga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
switch (event) {
case SND_SOC_DAPM_POST_PMU:
handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 1);
break;
case SND_SOC_DAPM_POST_PMD:
handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 0);
break;
} }
return 0;
}
static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
switch (event) {
case SND_SOC_DAPM_POST_PMU:
handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 1);
break;
case SND_SOC_DAPM_POST_PMD:
handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 0);
break;
}
return 0; return 0;
} }
...@@ -1190,11 +1224,15 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { ...@@ -1190,11 +1224,15 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
/* Output MUX controls */ /* Output MUX controls */
/* HandsfreeL/R */ /* HandsfreeL/R */
SND_SOC_DAPM_MUX_E("HandsfreeL Mux", TWL4030_REG_HFL_CTL, 5, 0, SND_SOC_DAPM_MUX("HandsfreeL Mux", SND_SOC_NOPM, 0, 0,
&twl4030_dapm_handsfreel_control, handsfree_event, &twl4030_dapm_handsfreel_control),
SND_SOC_DAPM_PGA_E("HandsfreeL PGA", SND_SOC_NOPM,
0, 0, NULL, 0, handsfreelpga_event,
SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("HandsfreeR Mux", TWL4030_REG_HFR_CTL, 5, 0, SND_SOC_DAPM_MUX("HandsfreeR Mux", SND_SOC_NOPM, 5, 0,
&twl4030_dapm_handsfreer_control, handsfree_event, &twl4030_dapm_handsfreer_control),
SND_SOC_DAPM_PGA_E("HandsfreeR PGA", SND_SOC_NOPM,
0, 0, NULL, 0, handsfreerpga_event,
SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
/* Vibra */ /* Vibra */
SND_SOC_DAPM_MUX("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0, SND_SOC_DAPM_MUX("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0,
...@@ -1303,11 +1341,13 @@ static const struct snd_soc_dapm_route intercon[] = { ...@@ -1303,11 +1341,13 @@ static const struct snd_soc_dapm_route intercon[] = {
{"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"}, {"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"},
{"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"}, {"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"},
{"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"}, {"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"},
{"HandsfreeL PGA", NULL, "HandsfreeL Mux"},
/* HandsfreeR */ /* HandsfreeR */
{"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"}, {"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"},
{"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"}, {"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"},
{"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"}, {"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"},
{"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"}, {"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"},
{"HandsfreeR PGA", NULL, "HandsfreeR Mux"},
/* Vibra */ /* Vibra */
{"Vibra Mux", "AudioL1", "DAC Left1"}, {"Vibra Mux", "AudioL1", "DAC Left1"},
{"Vibra Mux", "AudioR1", "DAC Right1"}, {"Vibra Mux", "AudioR1", "DAC Right1"},
...@@ -1324,8 +1364,8 @@ static const struct snd_soc_dapm_route intercon[] = { ...@@ -1324,8 +1364,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"HSOR", NULL, "HeadsetR PGA"}, {"HSOR", NULL, "HeadsetR PGA"},
{"CARKITL", NULL, "CarkitL Mixer"}, {"CARKITL", NULL, "CarkitL Mixer"},
{"CARKITR", NULL, "CarkitR Mixer"}, {"CARKITR", NULL, "CarkitR Mixer"},
{"HFL", NULL, "HandsfreeL Mux"}, {"HFL", NULL, "HandsfreeL PGA"},
{"HFR", NULL, "HandsfreeR Mux"}, {"HFR", NULL, "HandsfreeR PGA"},
{"Vibra Route", "Audio", "Vibra Mux"}, {"Vibra Route", "Audio", "Vibra Mux"},
{"VIBRA", NULL, "Vibra Route"}, {"VIBRA", NULL, "Vibra Route"},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment