aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/twl4030.c
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@nokia.com>2009-02-18 07:39:05 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-02-18 12:14:23 -0500
commit6bab83fd886564e96abcff62862732159535f600 (patch)
treec1dbe48756e7b21aa5eb00a757181a50f7f84c02 /sound/soc/codecs/twl4030.c
parent93b760b7072ca6972c15c798e97af3f830d8bbba (diff)
ASoC: TWL4030: Add digital loopback support
This patch adds the digital loopback/bypass support for twl4030 codec. The digital loopback will let the digimic0 (routed in the TX1 capture path inside of TWL4030) data to be routed back to the RX2 playback path (I2S stereo). It can also route the analog capture date routed through the TX1 back to RX2. Effectively the digital loopback is routing the audio from the TX1 capture path to the RX2 playback path. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/twl4030.c')
-rw-r--r--sound/soc/codecs/twl4030.c56
1 files changed, 50 insertions, 6 deletions
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index c26854b398d..535d8ce2c32 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -504,6 +504,25 @@ static const struct snd_kcontrol_new twl4030_dapm_abypassr2_control =
504static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control = 504static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control =
505 SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0); 505 SOC_DAPM_SINGLE("Switch", TWL4030_REG_ARXL2_APGA_CTL, 2, 1, 0);
506 506
507/* Digital bypass gain, 0 mutes the bypass */
508static const unsigned int twl4030_dapm_dbypass_tlv[] = {
509 TLV_DB_RANGE_HEAD(2),
510 0, 3, TLV_DB_SCALE_ITEM(-2400, 0, 1),
511 4, 7, TLV_DB_SCALE_ITEM(-1800, 600, 0),
512};
513
514/* Digital bypass left (TX1L -> RX2L) */
515static const struct snd_kcontrol_new twl4030_dapm_dbypassl_control =
516 SOC_DAPM_SINGLE_TLV("Volume",
517 TWL4030_REG_ATX2ARXPGA, 3, 7, 0,
518 twl4030_dapm_dbypass_tlv);
519
520/* Digital bypass right (TX1R -> RX2R) */
521static const struct snd_kcontrol_new twl4030_dapm_dbypassr_control =
522 SOC_DAPM_SINGLE_TLV("Volume",
523 TWL4030_REG_ATX2ARXPGA, 0, 7, 0,
524 twl4030_dapm_dbypass_tlv);
525
507static int micpath_event(struct snd_soc_dapm_widget *w, 526static int micpath_event(struct snd_soc_dapm_widget *w,
508 struct snd_kcontrol *kcontrol, int event) 527 struct snd_kcontrol *kcontrol, int event)
509{ 528{
@@ -608,12 +627,22 @@ static int bypass_event(struct snd_soc_dapm_widget *w,
608 unsigned char reg; 627 unsigned char reg;
609 628
610 reg = twl4030_read_reg_cache(w->codec, m->reg); 629 reg = twl4030_read_reg_cache(w->codec, m->reg);
611 if (reg & (1 << m->shift)) 630
612 twl4030->bypass_state |= 631 if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) {
613 (1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL)); 632 /* Analog bypass */
614 else 633 if (reg & (1 << m->shift))
615 twl4030->bypass_state &= 634 twl4030->bypass_state |=
616 ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL)); 635 (1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
636 else
637 twl4030->bypass_state &=
638 ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
639 } else {
640 /* Digital bypass */
641 if (reg & (0x7 << m->shift))
642 twl4030->bypass_state |= (1 << (m->shift ? 5 : 4));
643 else
644 twl4030->bypass_state &= ~(1 << (m->shift ? 5 : 4));
645 }
617 646
618 if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) { 647 if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) {
619 if (twl4030->bypass_state) 648 if (twl4030->bypass_state)
@@ -934,6 +963,14 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
934 &twl4030_dapm_abypassl2_control, 963 &twl4030_dapm_abypassl2_control,
935 bypass_event, SND_SOC_DAPM_POST_REG), 964 bypass_event, SND_SOC_DAPM_POST_REG),
936 965
966 /* Digital bypasses */
967 SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0,
968 &twl4030_dapm_dbypassl_control, bypass_event,
969 SND_SOC_DAPM_POST_REG),
970 SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0,
971 &twl4030_dapm_dbypassr_control, bypass_event,
972 SND_SOC_DAPM_POST_REG),
973
937 SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer", TWL4030_REG_AVDAC_CTL, 974 SND_SOC_DAPM_MIXER("Analog R1 Playback Mixer", TWL4030_REG_AVDAC_CTL,
938 0, 0, NULL, 0), 975 0, 0, NULL, 0),
939 SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer", TWL4030_REG_AVDAC_CTL, 976 SND_SOC_DAPM_MIXER("Analog L1 Playback Mixer", TWL4030_REG_AVDAC_CTL,
@@ -1118,6 +1155,13 @@ static const struct snd_soc_dapm_route intercon[] = {
1118 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"}, 1155 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"},
1119 {"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"}, 1156 {"Analog L2 Playback Mixer", NULL, "Left2 Analog Loopback"},
1120 1157
1158 /* Digital bypass routes */
1159 {"Right Digital Loopback", "Volume", "TX1 Capture Route"},
1160 {"Left Digital Loopback", "Volume", "TX1 Capture Route"},
1161
1162 {"Analog R2 Playback Mixer", NULL, "Right Digital Loopback"},
1163 {"Analog L2 Playback Mixer", NULL, "Left Digital Loopback"},
1164
1121}; 1165};
1122 1166
1123static int twl4030_add_widgets(struct snd_soc_codec *codec) 1167static int twl4030_add_widgets(struct snd_soc_codec *codec)