diff options
author | Peter Ujfalusi <peter.ujfalusi@nokia.com> | 2009-05-25 04:12:11 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-05-25 06:54:13 -0400 |
commit | 5a2e9a48b1d6de35ae5efea35d117133c3eb30f2 (patch) | |
tree | 264a6320bc0275043cbfe66a2214fd3e8075491b /sound/soc/codecs | |
parent | 0bc53a67ac831ec84f730a657dbcadd80a589ef5 (diff) |
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: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/twl4030.c | 78 |
1 files changed, 59 insertions, 19 deletions
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 9197fdd0a29d..17ddcb265134 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -546,27 +546,61 @@ static int micpath_event(struct snd_soc_dapm_widget *w, | |||
546 | return 0; | 546 | return 0; |
547 | } | 547 | } |
548 | 548 | ||
549 | static int handsfree_event(struct snd_soc_dapm_widget *w, | 549 | static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp) |
550 | struct snd_kcontrol *kcontrol, int event) | ||
551 | { | 550 | { |
552 | struct soc_enum *e = (struct soc_enum *)w->kcontrols->private_value; | ||
553 | unsigned char hs_ctl; | 551 | unsigned char hs_ctl; |
554 | 552 | ||
555 | hs_ctl = twl4030_read_reg_cache(w->codec, e->reg); | 553 | hs_ctl = twl4030_read_reg_cache(codec, reg); |
556 | 554 | ||
557 | if (hs_ctl & TWL4030_HF_CTL_REF_EN) { | 555 | if (ramp) { |
556 | /* HF ramp-up */ | ||
557 | hs_ctl |= TWL4030_HF_CTL_REF_EN; | ||
558 | twl4030_write(codec, reg, hs_ctl); | ||
559 | udelay(10); | ||
558 | hs_ctl |= TWL4030_HF_CTL_RAMP_EN; | 560 | hs_ctl |= TWL4030_HF_CTL_RAMP_EN; |
559 | twl4030_write(w->codec, e->reg, hs_ctl); | 561 | twl4030_write(codec, reg, hs_ctl); |
562 | udelay(40); | ||
560 | hs_ctl |= TWL4030_HF_CTL_LOOP_EN; | 563 | hs_ctl |= TWL4030_HF_CTL_LOOP_EN; |
561 | twl4030_write(w->codec, e->reg, hs_ctl); | ||
562 | hs_ctl |= TWL4030_HF_CTL_HB_EN; | 564 | hs_ctl |= TWL4030_HF_CTL_HB_EN; |
563 | twl4030_write(w->codec, e->reg, hs_ctl); | 565 | twl4030_write(codec, reg, hs_ctl); |
564 | } else { | 566 | } else { |
565 | hs_ctl &= ~(TWL4030_HF_CTL_RAMP_EN | TWL4030_HF_CTL_LOOP_EN | 567 | /* HF ramp-down */ |
566 | | TWL4030_HF_CTL_HB_EN); | 568 | hs_ctl &= ~TWL4030_HF_CTL_LOOP_EN; |
567 | twl4030_write(w->codec, e->reg, hs_ctl); | 569 | hs_ctl &= ~TWL4030_HF_CTL_HB_EN; |
570 | twl4030_write(codec, reg, hs_ctl); | ||
571 | hs_ctl &= ~TWL4030_HF_CTL_RAMP_EN; | ||
572 | twl4030_write(codec, reg, hs_ctl); | ||
573 | udelay(40); | ||
574 | hs_ctl &= ~TWL4030_HF_CTL_REF_EN; | ||
575 | twl4030_write(codec, reg, hs_ctl); | ||
568 | } | 576 | } |
577 | } | ||
569 | 578 | ||
579 | static int handsfreelpga_event(struct snd_soc_dapm_widget *w, | ||
580 | struct snd_kcontrol *kcontrol, int event) | ||
581 | { | ||
582 | switch (event) { | ||
583 | case SND_SOC_DAPM_POST_PMU: | ||
584 | handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 1); | ||
585 | break; | ||
586 | case SND_SOC_DAPM_POST_PMD: | ||
587 | handsfree_ramp(w->codec, TWL4030_REG_HFL_CTL, 0); | ||
588 | break; | ||
589 | } | ||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | static int handsfreerpga_event(struct snd_soc_dapm_widget *w, | ||
594 | struct snd_kcontrol *kcontrol, int event) | ||
595 | { | ||
596 | switch (event) { | ||
597 | case SND_SOC_DAPM_POST_PMU: | ||
598 | handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 1); | ||
599 | break; | ||
600 | case SND_SOC_DAPM_POST_PMD: | ||
601 | handsfree_ramp(w->codec, TWL4030_REG_HFR_CTL, 0); | ||
602 | break; | ||
603 | } | ||
570 | return 0; | 604 | return 0; |
571 | } | 605 | } |
572 | 606 | ||
@@ -1190,12 +1224,16 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
1190 | 1224 | ||
1191 | /* Output MUX controls */ | 1225 | /* Output MUX controls */ |
1192 | /* HandsfreeL/R */ | 1226 | /* HandsfreeL/R */ |
1193 | SND_SOC_DAPM_MUX_E("HandsfreeL Mux", TWL4030_REG_HFL_CTL, 5, 0, | 1227 | SND_SOC_DAPM_MUX("HandsfreeL Mux", SND_SOC_NOPM, 0, 0, |
1194 | &twl4030_dapm_handsfreel_control, handsfree_event, | 1228 | &twl4030_dapm_handsfreel_control), |
1195 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | 1229 | SND_SOC_DAPM_PGA_E("HandsfreeL PGA", SND_SOC_NOPM, |
1196 | SND_SOC_DAPM_MUX_E("HandsfreeR Mux", TWL4030_REG_HFR_CTL, 5, 0, | 1230 | 0, 0, NULL, 0, handsfreelpga_event, |
1197 | &twl4030_dapm_handsfreer_control, handsfree_event, | 1231 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), |
1198 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | 1232 | SND_SOC_DAPM_MUX("HandsfreeR Mux", SND_SOC_NOPM, 5, 0, |
1233 | &twl4030_dapm_handsfreer_control), | ||
1234 | SND_SOC_DAPM_PGA_E("HandsfreeR PGA", SND_SOC_NOPM, | ||
1235 | 0, 0, NULL, 0, handsfreerpga_event, | ||
1236 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | ||
1199 | /* Vibra */ | 1237 | /* Vibra */ |
1200 | SND_SOC_DAPM_MUX("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0, | 1238 | SND_SOC_DAPM_MUX("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0, |
1201 | &twl4030_dapm_vibra_control), | 1239 | &twl4030_dapm_vibra_control), |
@@ -1303,11 +1341,13 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1303 | {"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"}, | 1341 | {"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"}, |
1304 | {"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"}, | 1342 | {"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"}, |
1305 | {"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"}, | 1343 | {"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"}, |
1344 | {"HandsfreeL PGA", NULL, "HandsfreeL Mux"}, | ||
1306 | /* HandsfreeR */ | 1345 | /* HandsfreeR */ |
1307 | {"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"}, | 1346 | {"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"}, |
1308 | {"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"}, | 1347 | {"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"}, |
1309 | {"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"}, | 1348 | {"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"}, |
1310 | {"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"}, | 1349 | {"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"}, |
1350 | {"HandsfreeR PGA", NULL, "HandsfreeR Mux"}, | ||
1311 | /* Vibra */ | 1351 | /* Vibra */ |
1312 | {"Vibra Mux", "AudioL1", "DAC Left1"}, | 1352 | {"Vibra Mux", "AudioL1", "DAC Left1"}, |
1313 | {"Vibra Mux", "AudioR1", "DAC Right1"}, | 1353 | {"Vibra Mux", "AudioR1", "DAC Right1"}, |
@@ -1324,8 +1364,8 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1324 | {"HSOR", NULL, "HeadsetR PGA"}, | 1364 | {"HSOR", NULL, "HeadsetR PGA"}, |
1325 | {"CARKITL", NULL, "CarkitL Mixer"}, | 1365 | {"CARKITL", NULL, "CarkitL Mixer"}, |
1326 | {"CARKITR", NULL, "CarkitR Mixer"}, | 1366 | {"CARKITR", NULL, "CarkitR Mixer"}, |
1327 | {"HFL", NULL, "HandsfreeL Mux"}, | 1367 | {"HFL", NULL, "HandsfreeL PGA"}, |
1328 | {"HFR", NULL, "HandsfreeR Mux"}, | 1368 | {"HFR", NULL, "HandsfreeR PGA"}, |
1329 | {"Vibra Route", "Audio", "Vibra Mux"}, | 1369 | {"Vibra Route", "Audio", "Vibra Mux"}, |
1330 | {"VIBRA", NULL, "Vibra Route"}, | 1370 | {"VIBRA", NULL, "Vibra Route"}, |
1331 | 1371 | ||