diff options
-rw-r--r-- | sound/soc/codecs/twl4030.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index c26854b398d3..535d8ce2c328 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 = | |||
504 | static const struct snd_kcontrol_new twl4030_dapm_abypassl2_control = | 504 | static 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 */ | ||
508 | static 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) */ | ||
515 | static 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) */ | ||
521 | static 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 | |||
507 | static int micpath_event(struct snd_soc_dapm_widget *w, | 526 | static 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 | ||
1123 | static int twl4030_add_widgets(struct snd_soc_codec *codec) | 1167 | static int twl4030_add_widgets(struct snd_soc_codec *codec) |