ASoC: WCD9310: Add mono differential support for line outs
Allows multiple input signals to be mixed within the codec.
Also allows output in inverted phase.
Signed-off-by: Brad Rubin <brubin@codeaurora.org>
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index de1b199..4a527ee 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -92,8 +92,20 @@
static const struct snd_kcontrol_new tabla_snd_controls[] = {
SOC_SINGLE_TLV("LINEOUT1 Volume", TABLA_A_RX_LINE_1_GAIN, 0, 12, 1,
line_gain),
+ SOC_SINGLE_TLV("LINEOUT2 Volume", TABLA_A_RX_LINE_2_GAIN, 0, 12, 1,
+ line_gain),
SOC_SINGLE_TLV("LINEOUT3 Volume", TABLA_A_RX_LINE_3_GAIN, 0, 12, 1,
line_gain),
+ SOC_SINGLE_TLV("LINEOUT4 Volume", TABLA_A_RX_LINE_4_GAIN, 0, 12, 1,
+ line_gain),
+
+ SOC_SINGLE("RX1 CHAIN INVERT Switch", TABLA_A_CDC_RX1_B6_CTL, 4, 1, 0),
+ SOC_SINGLE("RX2 CHAIN INVERT Switch", TABLA_A_CDC_RX2_B6_CTL, 4, 1, 0),
+ SOC_SINGLE("RX3 CHAIN INVERT Switch", TABLA_A_CDC_RX3_B6_CTL, 4, 1, 0),
+ SOC_SINGLE("RX4 CHAIN INVERT Switch", TABLA_A_CDC_RX4_B6_CTL, 4, 1, 0),
+ SOC_SINGLE("RX5 CHAIN INVERT Switch", TABLA_A_CDC_RX5_B6_CTL, 4, 1, 0),
+ SOC_SINGLE("RX6 CHAIN INVERT Switch", TABLA_A_CDC_RX6_B6_CTL, 4, 1, 0),
+
SOC_SINGLE_TLV("HPHL Volume", TABLA_A_RX_HPH_L_GAIN, 0, 12, 1,
line_gain),
SOC_SINGLE_TLV("HPHR Volume", TABLA_A_RX_HPH_R_GAIN, 0, 12, 1,
@@ -171,12 +183,27 @@
static const struct soc_enum rx3_mix1_inp1_chain_enum =
SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
+static const struct soc_enum rx3_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
+
static const struct soc_enum rx4_mix1_inp1_chain_enum =
SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
+static const struct soc_enum rx4_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
+
static const struct soc_enum rx5_mix1_inp1_chain_enum =
SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX5_B1_CTL, 0, 12, rx_mix1_text);
+static const struct soc_enum rx5_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX5_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx6_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX6_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx6_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_RX6_B1_CTL, 4, 12, rx_mix1_text);
+
static const struct soc_enum sb_tx5_mux_enum =
SOC_ENUM_SINGLE(TABLA_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
@@ -218,12 +245,27 @@
static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
+static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
+
static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
+static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
+
static const struct snd_kcontrol_new rx5_mix1_inp1_mux =
SOC_DAPM_ENUM("RX5 MIX1 INP1 Mux", rx5_mix1_inp1_chain_enum);
+static const struct snd_kcontrol_new rx5_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX5 MIX1 INP2 Mux", rx5_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx6_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX6 MIX1 INP1 Mux", rx6_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx6_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX6 MIX1 INP2 Mux", rx6_mix1_inp2_chain_enum);
+
static const struct snd_kcontrol_new sb_tx5_mux =
SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
@@ -266,9 +308,16 @@
static const struct snd_kcontrol_new lineout1_switch =
SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_1_DAC_CTL, 6, 1, 0);
+static const struct snd_kcontrol_new lineout2_switch =
+ SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_2_DAC_CTL, 6, 1, 0);
+
static const struct snd_kcontrol_new lineout3_switch =
SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
+static const struct snd_kcontrol_new lineout4_switch =
+ SOC_DAPM_SINGLE("Switch", TABLA_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
+
+
static void tabla_codec_enable_adc_block(struct snd_soc_codec *codec,
int enable)
{
@@ -500,81 +549,17 @@
return 0;
}
-static int tabla_codec_reset_interpolator_1(struct snd_soc_dapm_widget *w,
+static int tabla_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL, 0x1,
- 0x1);
- snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL, 0x1,
- 0x0);
- break;
- }
- return 0;
-}
-
-static int tabla_codec_reset_interpolator_2(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL, 0x2,
- 0x2);
- snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL, 0x2,
- 0x0);
- break;
- }
- return 0;
-}
-
-static int tabla_codec_reset_interpolator_3(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL, 0x4,
- 0x4);
- snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL, 0x4,
- 0x0);
- break;
- }
- return 0;
-}
-
-static int tabla_codec_reset_interpolator_4(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL, 0x8,
- 0x8);
- snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL, 0x8,
- 0x0);
- break;
- }
- return 0;
-}
-
-static int tabla_codec_reset_interpolator_5(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL, 0x10,
- 0x10);
- snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL, 0x10,
- 0x0);
+ snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL,
+ 1 << w->shift, 1 << w->shift);
+ snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_RESET_CTL,
+ 1 << w->shift, 0x0);
break;
}
return 0;
@@ -596,7 +581,7 @@
SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_PGA("RX BIAS", TABLA_A_RX_COM_BIAS, 7, 0, NULL, 0),
SND_SOC_DAPM_MUX_E("RX1 MIX1 INP1", TABLA_A_CDC_CLK_RX_B1_CTL, 0, 0,
- &rx_mix1_inp1_mux, tabla_codec_reset_interpolator_1,
+ &rx_mix1_inp1_mux, tabla_codec_reset_interpolator,
SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_AIF_IN("SLIM RX1", "AIF1 Playback", 0,
TABLA_A_CDC_RX1_B6_CTL, 5, 0),
@@ -606,7 +591,7 @@
tabla_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_MUX_E("RX2 MIX1 INP1", TABLA_A_CDC_CLK_RX_B1_CTL, 1, 0,
- &rx2_mix1_inp1_mux, tabla_codec_reset_interpolator_2,
+ &rx2_mix1_inp1_mux, tabla_codec_reset_interpolator,
SND_SOC_DAPM_PRE_PMU),
SND_SOC_DAPM_AIF_IN("SLIM RX2", "AIF1 Playback", 0,
TABLA_A_CDC_RX2_B6_CTL, 5, 0),
@@ -623,26 +608,54 @@
/* Speaker */
SND_SOC_DAPM_OUTPUT("LINEOUT"),
+
SND_SOC_DAPM_PGA_E("LINEOUT1", TABLA_A_RX_LINE_CNP_EN, 0, 0, NULL, 0,
tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_SWITCH("LINEOUT1 DAC", TABLA_A_RX_LINE_1_DAC_CTL, 7, 0,
- &lineout1_switch),
- SND_SOC_DAPM_MUX_E("RX3 MIX1 INP1", TABLA_A_CDC_CLK_RX_B1_CTL, 2, 0,
- &rx3_mix1_inp1_mux, tabla_codec_reset_interpolator_3,
- SND_SOC_DAPM_PRE_PMU),
-
+ SND_SOC_DAPM_PGA_E("LINEOUT2", TABLA_A_RX_LINE_CNP_EN, 1, 0, NULL, 0,
+ tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA_E("LINEOUT3", TABLA_A_RX_LINE_CNP_EN, 2, 0, NULL, 0,
tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("LINEOUT4", TABLA_A_RX_LINE_CNP_EN, 3, 0, NULL, 0,
+ tabla_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SWITCH("LINEOUT1 DAC", TABLA_A_RX_LINE_1_DAC_CTL, 7, 0,
+ &lineout1_switch),
+ SND_SOC_DAPM_SWITCH("LINEOUT2 DAC", TABLA_A_RX_LINE_2_DAC_CTL, 7, 0,
+ &lineout2_switch),
SND_SOC_DAPM_SWITCH("LINEOUT3 DAC", TABLA_A_RX_LINE_3_DAC_CTL, 7, 0,
&lineout3_switch),
- SND_SOC_DAPM_MUX_E("RX4 MIX1 INP1", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0,
- &rx4_mix1_inp1_mux, tabla_codec_reset_interpolator_4,
- SND_SOC_DAPM_PRE_PMU),
- SND_SOC_DAPM_MUX_E("RX5 MIX1 INP1", TABLA_A_CDC_CLK_RX_B1_CTL, 4, 0,
- &rx5_mix1_inp1_mux, tabla_codec_reset_interpolator_5,
- SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_SWITCH("LINEOUT4 DAC", TABLA_A_RX_LINE_4_DAC_CTL, 7, 0,
+ &lineout4_switch),
+
+ SND_SOC_DAPM_PGA_E("RX3 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL, 0,
+ tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_PGA_E("RX4 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL, 0,
+ tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_PGA_E("RX5 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL, 0,
+ tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_PGA_E("RX6 MIX1", TABLA_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL, 0,
+ tabla_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx4_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx4_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx5_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx5_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx6_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx6_mix1_inp2_mux),
/* TX */
SND_SOC_DAPM_INPUT("AMIC1"),
@@ -761,17 +774,46 @@
{"RX2 CP", NULL, "RX2 MIX1 INP1"},
{"RX2 MIX1 INP1", "RX2", "RX BIAS"},
- /* Speaker (RX MIX3 and RX MIX4) */
{"LINEOUT", NULL, "LINEOUT1"},
- {"LINEOUT1", NULL, "LINEOUT1 DAC"},
- {"LINEOUT1 DAC", "Switch", "RX3 MIX1 INP1"},
- {"RX3 MIX1 INP1", "RX1", "RX BIAS"},
-
+ {"LINEOUT", NULL, "LINEOUT2"},
{"LINEOUT", NULL, "LINEOUT3"},
+ {"LINEOUT", NULL, "LINEOUT4"},
+
+ {"LINEOUT1", NULL, "LINEOUT1 DAC"},
+ {"LINEOUT2", NULL, "LINEOUT2 DAC"},
{"LINEOUT3", NULL, "LINEOUT3 DAC"},
- {"LINEOUT3 DAC", "Switch", "RX5 MIX1 INP1"},
+ {"LINEOUT4", NULL, "LINEOUT4 DAC"},
+
+ {"LINEOUT1 DAC", "Switch", "RX3 MIX1"},
+ {"LINEOUT2 DAC", "Switch", "RX4 MIX1"},
+ {"LINEOUT3 DAC", "Switch", "RX5 MIX1"},
+ {"LINEOUT4 DAC", "Switch", "RX6 MIX1"},
+
+ {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
+ {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
+ {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
+ {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
+ {"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
+ {"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
+ {"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
+ {"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
+
+ {"RX3 MIX1 INP1", "RX1", "RX BIAS"},
+ {"RX3 MIX1 INP1", "RX2", "RX BIAS"},
+ {"RX3 MIX1 INP2", "RX1", "RX BIAS"},
+ {"RX3 MIX1 INP2", "RX2", "RX BIAS"},
+ {"RX4 MIX1 INP1", "RX1", "RX BIAS"},
{"RX4 MIX1 INP1", "RX2", "RX BIAS"},
+ {"RX4 MIX1 INP2", "RX1", "RX BIAS"},
+ {"RX4 MIX1 INP2", "RX2", "RX BIAS"},
+ {"RX5 MIX1 INP1", "RX1", "RX BIAS"},
{"RX5 MIX1 INP1", "RX2", "RX BIAS"},
+ {"RX5 MIX1 INP2", "RX1", "RX BIAS"},
+ {"RX5 MIX1 INP2", "RX2", "RX BIAS"},
+ {"RX6 MIX1 INP1", "RX1", "RX BIAS"},
+ {"RX6 MIX1 INP1", "RX2", "RX BIAS"},
+ {"RX6 MIX1 INP2", "RX1", "RX BIAS"},
+ {"RX6 MIX1 INP2", "RX2", "RX BIAS"},
/* Handset TX */
{"DEC5 MUX", "ADC2", "ADC2"},