Alsa-devel
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
December 2019
- 123 participants
- 372 discussions
[alsa-devel] Applied "ASoC: wcd934x: add playback dapm widgets" to the asoc tree
by Mark Brown 25 Dec '19
by Mark Brown 25 Dec '19
25 Dec '19
The patch
ASoC: wcd934x: add playback dapm widgets
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From dd9eb19b567303e4b92747dcfb5deedb182af111 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Date: Thu, 19 Dec 2019 10:31:47 +0000
Subject: [PATCH] ASoC: wcd934x: add playback dapm widgets
This patch adds required dapm widgets for playback.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Link: https://lore.kernel.org/r/20191219103153.14875-6-srinivas.kandagatla@linaro…
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart(a)linux.intel.com>
Signed-off-by: Mark Brown <broonie(a)kernel.org>
---
sound/soc/codecs/wcd934x.c | 1550 ++++++++++++++++++++++++++++++++++++
1 file changed, 1550 insertions(+)
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index 27a864f2ff77..556c051f7f99 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -412,6 +412,94 @@ static const char * const rx_hph_mode_mux_text[] = {
"Class-H Hi-Fi Low Power"
};
+static const char *const slim_rx_mux_text[] = {
+ "ZERO", "AIF1_PB", "AIF2_PB", "AIF3_PB", "AIF4_PB",
+};
+
+static const char * const rx_int0_7_mix_mux_text[] = {
+ "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5",
+ "RX6", "RX7", "PROXIMITY"
+};
+
+static const char * const rx_int_mix_mux_text[] = {
+ "ZERO", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5",
+ "RX6", "RX7"
+};
+
+static const char * const rx_prim_mix_text[] = {
+ "ZERO", "DEC0", "DEC1", "IIR0", "IIR1", "RX0", "RX1", "RX2",
+ "RX3", "RX4", "RX5", "RX6", "RX7"
+};
+
+static const char * const rx_sidetone_mix_text[] = {
+ "ZERO", "SRC0", "SRC1", "SRC_SUM"
+};
+
+static const char * const iir_inp_mux_text[] = {
+ "ZERO", "DEC0", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6",
+ "DEC7", "DEC8", "RX0", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
+};
+
+static const char * const rx_int_dem_inp_mux_text[] = {
+ "NORMAL_DSM_OUT", "CLSH_DSM_OUT",
+};
+
+static const char * const rx_int0_1_interp_mux_text[] = {
+ "ZERO", "RX INT0_1 MIX1",
+};
+
+static const char * const rx_int1_1_interp_mux_text[] = {
+ "ZERO", "RX INT1_1 MIX1",
+};
+
+static const char * const rx_int2_1_interp_mux_text[] = {
+ "ZERO", "RX INT2_1 MIX1",
+};
+
+static const char * const rx_int3_1_interp_mux_text[] = {
+ "ZERO", "RX INT3_1 MIX1",
+};
+
+static const char * const rx_int4_1_interp_mux_text[] = {
+ "ZERO", "RX INT4_1 MIX1",
+};
+
+static const char * const rx_int7_1_interp_mux_text[] = {
+ "ZERO", "RX INT7_1 MIX1",
+};
+
+static const char * const rx_int8_1_interp_mux_text[] = {
+ "ZERO", "RX INT8_1 MIX1",
+};
+
+static const char * const rx_int0_2_interp_mux_text[] = {
+ "ZERO", "RX INT0_2 MUX",
+};
+
+static const char * const rx_int1_2_interp_mux_text[] = {
+ "ZERO", "RX INT1_2 MUX",
+};
+
+static const char * const rx_int2_2_interp_mux_text[] = {
+ "ZERO", "RX INT2_2 MUX",
+};
+
+static const char * const rx_int3_2_interp_mux_text[] = {
+ "ZERO", "RX INT3_2 MUX",
+};
+
+static const char * const rx_int4_2_interp_mux_text[] = {
+ "ZERO", "RX INT4_2 MUX",
+};
+
+static const char * const rx_int7_2_interp_mux_text[] = {
+ "ZERO", "RX INT7_2 MUX",
+};
+
+static const char * const rx_int8_2_interp_mux_text[] = {
+ "ZERO", "RX INT8_2 MUX",
+};
+
static const struct soc_enum cf_dec0_enum =
SOC_ENUM_SINGLE(WCD934X_CDC_TX0_TX_PATH_CFG0, 5, 3, cf_text);
@@ -485,6 +573,236 @@ static const struct soc_enum rx_hph_mode_mux_enum =
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
rx_hph_mode_mux_text);
+static const struct soc_enum slim_rx_mux_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim_rx_mux_text), slim_rx_mux_text);
+
+static const struct soc_enum rx_int0_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1, 0, 10,
+ rx_int0_7_mix_mux_text);
+
+static const struct soc_enum rx_int1_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1, 0, 9,
+ rx_int_mix_mux_text);
+
+static const struct soc_enum rx_int2_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1, 0, 9,
+ rx_int_mix_mux_text);
+
+static const struct soc_enum rx_int3_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1, 0, 9,
+ rx_int_mix_mux_text);
+
+static const struct soc_enum rx_int4_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1, 0, 9,
+ rx_int_mix_mux_text);
+
+static const struct soc_enum rx_int7_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1, 0, 10,
+ rx_int0_7_mix_mux_text);
+
+static const struct soc_enum rx_int8_2_mux_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1, 0, 9,
+ rx_int_mix_mux_text);
+
+static const struct soc_enum rx_int0_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int0_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int0_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT0_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int1_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int1_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int1_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT1_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int2_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int2_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int2_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT2_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int3_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int3_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int3_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT3_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int4_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int4_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int4_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int7_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int7_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int7_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT7_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int8_1_mix_inp0_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0, 0, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int8_1_mix_inp1_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG0, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int8_1_mix_inp2_chain_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1, 4, 13,
+ rx_prim_mix_text);
+
+static const struct soc_enum rx_int0_mix2_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 0, 4,
+ rx_sidetone_mix_text);
+
+static const struct soc_enum rx_int1_mix2_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2, 4,
+ rx_sidetone_mix_text);
+
+static const struct soc_enum rx_int2_mix2_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4, 4,
+ rx_sidetone_mix_text);
+
+static const struct soc_enum rx_int3_mix2_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 6, 4,
+ rx_sidetone_mix_text);
+
+static const struct soc_enum rx_int4_mix2_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1, 0, 4,
+ rx_sidetone_mix_text);
+
+static const struct soc_enum rx_int7_mix2_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1, 2, 4,
+ rx_sidetone_mix_text);
+
+static const struct soc_enum iir0_inp0_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir0_inp1_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir0_inp2_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir0_inp3_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir1_inp0_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir1_inp1_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir1_inp2_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum iir1_inp3_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3,
+ 0, 18, iir_inp_mux_text);
+
+static const struct soc_enum rx_int0_dem_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX0_RX_PATH_SEC0, 0,
+ ARRAY_SIZE(rx_int_dem_inp_mux_text),
+ rx_int_dem_inp_mux_text);
+
+static const struct soc_enum rx_int1_dem_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX1_RX_PATH_SEC0, 0,
+ ARRAY_SIZE(rx_int_dem_inp_mux_text),
+ rx_int_dem_inp_mux_text);
+
+static const struct soc_enum rx_int2_dem_inp_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_RX2_RX_PATH_SEC0, 0,
+ ARRAY_SIZE(rx_int_dem_inp_mux_text),
+ rx_int_dem_inp_mux_text);
+static const struct soc_enum rx_int0_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2,
+ rx_int0_1_interp_mux_text);
+
+static const struct soc_enum rx_int1_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2,
+ rx_int1_1_interp_mux_text);
+
+static const struct soc_enum rx_int2_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2,
+ rx_int2_1_interp_mux_text);
+
+static const struct soc_enum rx_int3_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int3_1_interp_mux_text);
+
+static const struct soc_enum rx_int4_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int4_1_interp_mux_text);
+
+static const struct soc_enum rx_int7_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int7_1_interp_mux_text);
+
+static const struct soc_enum rx_int8_1_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int8_1_interp_mux_text);
+
+static const struct soc_enum rx_int0_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int0_2_interp_mux_text);
+
+static const struct soc_enum rx_int1_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int1_2_interp_mux_text);
+
+static const struct soc_enum rx_int2_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int2_2_interp_mux_text);
+
+static const struct soc_enum rx_int3_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int3_2_interp_mux_text);
+
+static const struct soc_enum rx_int4_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int4_2_interp_mux_text);
+
+static const struct soc_enum rx_int7_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int7_2_interp_mux_text);
+
+static const struct soc_enum rx_int8_2_interp_mux_enum =
+ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int8_2_interp_mux_text);
+
static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd,
int sido_src)
{
@@ -639,6 +957,22 @@ static int __wcd934x_cdc_mclk_enable(struct wcd934x_codec *wcd, bool enable)
return ret;
}
+static int wcd934x_codec_enable_mclk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kc, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ return __wcd934x_cdc_mclk_enable(wcd, true);
+ case SND_SOC_DAPM_POST_PMD:
+ return __wcd934x_cdc_mclk_enable(wcd, false);
+ }
+
+ return 0;
+}
+
static int wcd934x_get_version(struct wcd934x_codec *wcd)
{
int val1, val2, ver, ret;
@@ -1814,6 +2148,311 @@ static int wcd934x_rx_hph_mode_put(struct snd_kcontrol *kc,
return 0;
}
+static int slim_rx_mux_get(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kc);
+ struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kc);
+ struct wcd934x_codec *wcd = dev_get_drvdata(dapm->dev);
+
+ ucontrol->value.enumerated.item[0] = wcd->rx_port_value[w->shift];
+
+ return 0;
+}
+
+static int slim_rx_mux_put(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kc);
+ struct wcd934x_codec *wcd = dev_get_drvdata(w->dapm->dev);
+ struct soc_enum *e = (struct soc_enum *)kc->private_value;
+ struct snd_soc_dapm_update *update = NULL;
+ u32 port_id = w->shift;
+
+ if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0])
+ return 0;
+
+ wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0];
+
+ switch (wcd->rx_port_value[port_id]) {
+ case 0:
+ list_del_init(&wcd->rx_chs[port_id].list);
+ break;
+ case 1:
+ list_add_tail(&wcd->rx_chs[port_id].list,
+ &wcd->dai[AIF1_PB].slim_ch_list);
+ break;
+ case 2:
+ list_add_tail(&wcd->rx_chs[port_id].list,
+ &wcd->dai[AIF2_PB].slim_ch_list);
+ break;
+ case 3:
+ list_add_tail(&wcd->rx_chs[port_id].list,
+ &wcd->dai[AIF3_PB].slim_ch_list);
+ break;
+ case 4:
+ list_add_tail(&wcd->rx_chs[port_id].list,
+ &wcd->dai[AIF4_PB].slim_ch_list);
+ break;
+ default:
+ dev_err(wcd->dev, "Unknown AIF %d\n",
+ wcd->rx_port_value[port_id]);
+ goto err;
+ }
+
+ snd_soc_dapm_mux_update_power(w->dapm, kc, wcd->rx_port_value[port_id],
+ e, update);
+
+ return 0;
+err:
+ return -EINVAL;
+}
+
+static int wcd934x_int_dem_inp_mux_put(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_enum *e = (struct soc_enum *)kc->private_value;
+ struct snd_soc_component *component;
+ int reg, val, ret;
+
+ component = snd_soc_dapm_kcontrol_component(kc);
+ val = ucontrol->value.enumerated.item[0];
+ if (e->reg == WCD934X_CDC_RX0_RX_PATH_SEC0)
+ reg = WCD934X_CDC_RX0_RX_PATH_CFG0;
+ else if (e->reg == WCD934X_CDC_RX1_RX_PATH_SEC0)
+ reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
+ else if (e->reg == WCD934X_CDC_RX2_RX_PATH_SEC0)
+ reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
+ else
+ return -EINVAL;
+
+ /* Set Look Ahead Delay */
+ if (val)
+ snd_soc_component_update_bits(component, reg,
+ WCD934X_RX_DLY_ZN_EN_MASK,
+ WCD934X_RX_DLY_ZN_ENABLE);
+ else
+ snd_soc_component_update_bits(component, reg,
+ WCD934X_RX_DLY_ZN_EN_MASK,
+ WCD934X_RX_DLY_ZN_DISABLE);
+
+ ret = snd_soc_dapm_put_enum_double(kc, ucontrol);
+
+ return ret;
+}
+
+static const struct snd_kcontrol_new rx_int0_2_mux =
+ SOC_DAPM_ENUM("RX INT0_2 MUX Mux", rx_int0_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int1_2_mux =
+ SOC_DAPM_ENUM("RX INT1_2 MUX Mux", rx_int1_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int2_2_mux =
+ SOC_DAPM_ENUM("RX INT2_2 MUX Mux", rx_int2_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int3_2_mux =
+ SOC_DAPM_ENUM("RX INT3_2 MUX Mux", rx_int3_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int4_2_mux =
+ SOC_DAPM_ENUM("RX INT4_2 MUX Mux", rx_int4_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int7_2_mux =
+ SOC_DAPM_ENUM("RX INT7_2 MUX Mux", rx_int7_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int8_2_mux =
+ SOC_DAPM_ENUM("RX INT8_2 MUX Mux", rx_int8_2_mux_chain_enum);
+
+static const struct snd_kcontrol_new rx_int0_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT0_1 MIX1 INP0 Mux", rx_int0_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int0_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT0_1 MIX1 INP1 Mux", rx_int0_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int0_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT0_1 MIX1 INP2 Mux", rx_int0_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int1_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT1_1 MIX1 INP0 Mux", rx_int1_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int1_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT1_1 MIX1 INP1 Mux", rx_int1_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int1_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT1_1 MIX1 INP2 Mux", rx_int1_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int2_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT2_1 MIX1 INP0 Mux", rx_int2_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int2_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT2_1 MIX1 INP1 Mux", rx_int2_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int2_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT2_1 MIX1 INP2 Mux", rx_int2_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int3_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT3_1 MIX1 INP0 Mux", rx_int3_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int3_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT3_1 MIX1 INP1 Mux", rx_int3_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int3_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT3_1 MIX1 INP2 Mux", rx_int3_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int4_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT4_1 MIX1 INP0 Mux", rx_int4_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int4_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT4_1 MIX1 INP1 Mux", rx_int4_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int4_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT4_1 MIX1 INP2 Mux", rx_int4_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int7_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT7_1 MIX1 INP0 Mux", rx_int7_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int7_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT7_1 MIX1 INP1 Mux", rx_int7_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int7_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT7_1 MIX1 INP2 Mux", rx_int7_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int8_1_mix_inp0_mux =
+ SOC_DAPM_ENUM("RX INT8_1 MIX1 INP0 Mux", rx_int8_1_mix_inp0_chain_enum);
+
+static const struct snd_kcontrol_new rx_int8_1_mix_inp1_mux =
+ SOC_DAPM_ENUM("RX INT8_1 MIX1 INP1 Mux", rx_int8_1_mix_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_int8_1_mix_inp2_mux =
+ SOC_DAPM_ENUM("RX INT8_1 MIX1 INP2 Mux", rx_int8_1_mix_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_int0_mix2_inp_mux =
+ SOC_DAPM_ENUM("RX INT0 MIX2 INP Mux", rx_int0_mix2_inp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int1_mix2_inp_mux =
+ SOC_DAPM_ENUM("RX INT1 MIX2 INP Mux", rx_int1_mix2_inp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int2_mix2_inp_mux =
+ SOC_DAPM_ENUM("RX INT2 MIX2 INP Mux", rx_int2_mix2_inp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int3_mix2_inp_mux =
+ SOC_DAPM_ENUM("RX INT3 MIX2 INP Mux", rx_int3_mix2_inp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int4_mix2_inp_mux =
+ SOC_DAPM_ENUM("RX INT4 MIX2 INP Mux", rx_int4_mix2_inp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int7_mix2_inp_mux =
+ SOC_DAPM_ENUM("RX INT7 MIX2 INP Mux", rx_int7_mix2_inp_mux_enum);
+
+static const struct snd_kcontrol_new iir0_inp0_mux =
+ SOC_DAPM_ENUM("IIR0 INP0 Mux", iir0_inp0_mux_enum);
+static const struct snd_kcontrol_new iir0_inp1_mux =
+ SOC_DAPM_ENUM("IIR0 INP1 Mux", iir0_inp1_mux_enum);
+static const struct snd_kcontrol_new iir0_inp2_mux =
+ SOC_DAPM_ENUM("IIR0 INP2 Mux", iir0_inp2_mux_enum);
+static const struct snd_kcontrol_new iir0_inp3_mux =
+ SOC_DAPM_ENUM("IIR0 INP3 Mux", iir0_inp3_mux_enum);
+
+static const struct snd_kcontrol_new iir1_inp0_mux =
+ SOC_DAPM_ENUM("IIR1 INP0 Mux", iir1_inp0_mux_enum);
+static const struct snd_kcontrol_new iir1_inp1_mux =
+ SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
+static const struct snd_kcontrol_new iir1_inp2_mux =
+ SOC_DAPM_ENUM("IIR1 INP2 Mux", iir1_inp2_mux_enum);
+static const struct snd_kcontrol_new iir1_inp3_mux =
+ SOC_DAPM_ENUM("IIR1 INP3 Mux", iir1_inp3_mux_enum);
+
+static const struct snd_kcontrol_new slim_rx_mux[WCD934X_RX_MAX] = {
+ SOC_DAPM_ENUM_EXT("SLIM RX0 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX1 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX2 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX3 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX4 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX5 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX6 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+ SOC_DAPM_ENUM_EXT("SLIM RX7 Mux", slim_rx_mux_enum,
+ slim_rx_mux_get, slim_rx_mux_put),
+};
+
+static const struct snd_kcontrol_new rx_int1_asrc_switch[] = {
+ SOC_DAPM_SINGLE("HPHL Switch", SND_SOC_NOPM, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new rx_int2_asrc_switch[] = {
+ SOC_DAPM_SINGLE("HPHR Switch", SND_SOC_NOPM, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new rx_int3_asrc_switch[] = {
+ SOC_DAPM_SINGLE("LO1 Switch", SND_SOC_NOPM, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new rx_int4_asrc_switch[] = {
+ SOC_DAPM_SINGLE("LO2 Switch", SND_SOC_NOPM, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new rx_int0_dem_inp_mux =
+ SOC_DAPM_ENUM_EXT("RX INT0 DEM MUX Mux", rx_int0_dem_inp_mux_enum,
+ snd_soc_dapm_get_enum_double,
+ wcd934x_int_dem_inp_mux_put);
+
+static const struct snd_kcontrol_new rx_int1_dem_inp_mux =
+ SOC_DAPM_ENUM_EXT("RX INT1 DEM MUX Mux", rx_int1_dem_inp_mux_enum,
+ snd_soc_dapm_get_enum_double,
+ wcd934x_int_dem_inp_mux_put);
+
+static const struct snd_kcontrol_new rx_int2_dem_inp_mux =
+ SOC_DAPM_ENUM_EXT("RX INT2 DEM MUX Mux", rx_int2_dem_inp_mux_enum,
+ snd_soc_dapm_get_enum_double,
+ wcd934x_int_dem_inp_mux_put);
+
+static const struct snd_kcontrol_new rx_int0_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT0_1 INTERP Mux", rx_int0_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int1_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT1_1 INTERP Mux", rx_int1_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int2_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT2_1 INTERP Mux", rx_int2_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int3_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT3_1 INTERP Mux", rx_int3_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int4_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT4_1 INTERP Mux", rx_int4_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int7_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT7_1 INTERP Mux", rx_int7_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int8_1_interp_mux =
+ SOC_DAPM_ENUM("RX INT8_1 INTERP Mux", rx_int8_1_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int0_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT0_2 INTERP Mux", rx_int0_2_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int1_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT1_2 INTERP Mux", rx_int1_2_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int2_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT2_2 INTERP Mux", rx_int2_2_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int3_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT3_2 INTERP Mux", rx_int3_2_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int4_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT4_2 INTERP Mux", rx_int4_2_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int7_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT7_2 INTERP Mux", rx_int7_2_interp_mux_enum);
+
+static const struct snd_kcontrol_new rx_int8_2_interp_mux =
+ SOC_DAPM_ENUM("RX INT8_2 INTERP Mux", rx_int8_2_interp_mux_enum);
+
static const struct snd_kcontrol_new wcd934x_snd_controls[] = {
/* Gain Controls */
SOC_SINGLE_TLV("EAR PA Volume", WCD934X_ANA_EAR, 4, 4, 1, ear_pa_gain),
@@ -1983,12 +2622,923 @@ static const struct snd_kcontrol_new wcd934x_snd_controls[] = {
wcd934x_compander_get, wcd934x_compander_set),
};
+static void wcd934x_codec_enable_int_port(struct wcd_slim_codec_dai_data *dai,
+ struct snd_soc_component *component)
+{
+ int port_num = 0;
+ unsigned short reg = 0;
+ unsigned int val = 0;
+ struct wcd934x_codec *wcd = dev_get_drvdata(component->dev);
+ struct wcd934x_slim_ch *ch;
+
+ list_for_each_entry(ch, &dai->slim_ch_list, list) {
+ if (ch->port >= WCD934X_RX_START) {
+ port_num = ch->port - WCD934X_RX_START;
+ reg = WCD934X_SLIM_PGD_PORT_INT_EN0 + (port_num / 8);
+ } else {
+ port_num = ch->port;
+ reg = WCD934X_SLIM_PGD_PORT_INT_TX_EN0 + (port_num / 8);
+ }
+
+ regmap_read(wcd->if_regmap, reg, &val);
+ if (!(val & BIT(port_num % 8)))
+ regmap_write(wcd->if_regmap, reg,
+ val | BIT(port_num % 8));
+ }
+}
+
+static int wcd934x_codec_enable_slim(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kc, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = snd_soc_component_get_drvdata(comp);
+ struct wcd_slim_codec_dai_data *dai = &wcd->dai[w->shift];
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ wcd934x_codec_enable_int_port(dai, comp);
+ break;
+ }
+
+ return 0;
+}
+
+static void wcd934x_codec_hd2_control(struct snd_soc_component *component,
+ u16 interp_idx, int event)
+{
+ u16 hd2_scale_reg;
+ u16 hd2_enable_reg = 0;
+
+ switch (interp_idx) {
+ case INTERP_HPHL:
+ hd2_scale_reg = WCD934X_CDC_RX1_RX_PATH_SEC3;
+ hd2_enable_reg = WCD934X_CDC_RX1_RX_PATH_CFG0;
+ break;
+ case INTERP_HPHR:
+ hd2_scale_reg = WCD934X_CDC_RX2_RX_PATH_SEC3;
+ hd2_enable_reg = WCD934X_CDC_RX2_RX_PATH_CFG0;
+ break;
+ default:
+ return;
+ }
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ snd_soc_component_update_bits(component, hd2_scale_reg,
+ WCD934X_CDC_RX_PATH_SEC_HD2_ALPHA_MASK,
+ WCD934X_CDC_RX_PATH_SEC_HD2_ALPHA_0P3125);
+ snd_soc_component_update_bits(component, hd2_enable_reg,
+ WCD934X_CDC_RX_PATH_CFG_HD2_EN_MASK,
+ WCD934X_CDC_RX_PATH_CFG_HD2_ENABLE);
+ }
+
+ if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ snd_soc_component_update_bits(component, hd2_enable_reg,
+ WCD934X_CDC_RX_PATH_CFG_HD2_EN_MASK,
+ WCD934X_CDC_RX_PATH_CFG_HD2_DISABLE);
+ snd_soc_component_update_bits(component, hd2_scale_reg,
+ WCD934X_CDC_RX_PATH_SEC_HD2_ALPHA_MASK,
+ WCD934X_CDC_RX_PATH_SEC_HD2_ALPHA_0P0000);
+ }
+}
+
+static void wcd934x_codec_hphdelay_lutbypass(struct snd_soc_component *comp,
+ u16 interp_idx, int event)
+{
+ u8 hph_dly_mask;
+ u16 hph_lut_bypass_reg = 0;
+ u16 hph_comp_ctrl7 = 0;
+
+ switch (interp_idx) {
+ case INTERP_HPHL:
+ hph_dly_mask = 1;
+ hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHL_COMP_LUT;
+ hph_comp_ctrl7 = WCD934X_CDC_COMPANDER1_CTL7;
+ break;
+ case INTERP_HPHR:
+ hph_dly_mask = 2;
+ hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHR_COMP_LUT;
+ hph_comp_ctrl7 = WCD934X_CDC_COMPANDER2_CTL7;
+ break;
+ default:
+ return;
+ }
+
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ snd_soc_component_update_bits(comp, WCD934X_CDC_CLSH_TEST0,
+ hph_dly_mask, 0x0);
+ snd_soc_component_update_bits(comp, hph_lut_bypass_reg,
+ WCD934X_HPH_LUT_BYPASS_MASK,
+ WCD934X_HPH_LUT_BYPASS_ENABLE);
+ }
+
+ if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ snd_soc_component_update_bits(comp, WCD934X_CDC_CLSH_TEST0,
+ hph_dly_mask, hph_dly_mask);
+ snd_soc_component_update_bits(comp, hph_lut_bypass_reg,
+ WCD934X_HPH_LUT_BYPASS_MASK,
+ WCD934X_HPH_LUT_BYPASS_DISABLE);
+ }
+}
+
+static int wcd934x_config_compander(struct snd_soc_component *comp,
+ int interp_n, int event)
+{
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+ int compander;
+ u16 comp_ctl0_reg, rx_path_cfg0_reg;
+
+ /* EAR does not have compander */
+ if (!interp_n)
+ return 0;
+
+ compander = interp_n - 1;
+ if (!wcd->comp_enabled[compander])
+ return 0;
+
+ comp_ctl0_reg = WCD934X_CDC_COMPANDER1_CTL0 + (compander * 8);
+ rx_path_cfg0_reg = WCD934X_CDC_RX1_RX_PATH_CFG0 + (compander * 20);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Enable Compander Clock */
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_CLK_EN_MASK,
+ WCD934X_COMP_CLK_ENABLE);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_SOFT_RST_MASK,
+ WCD934X_COMP_SOFT_RST_ENABLE);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_SOFT_RST_MASK,
+ WCD934X_COMP_SOFT_RST_DISABLE);
+ snd_soc_component_update_bits(comp, rx_path_cfg0_reg,
+ WCD934X_HPH_CMP_EN_MASK,
+ WCD934X_HPH_CMP_ENABLE);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_component_update_bits(comp, rx_path_cfg0_reg,
+ WCD934X_HPH_CMP_EN_MASK,
+ WCD934X_HPH_CMP_DISABLE);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_HALT_MASK,
+ WCD934X_COMP_HALT);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_SOFT_RST_MASK,
+ WCD934X_COMP_SOFT_RST_ENABLE);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_SOFT_RST_MASK,
+ WCD934X_COMP_SOFT_RST_DISABLE);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_CLK_EN_MASK, 0x0);
+ snd_soc_component_update_bits(comp, comp_ctl0_reg,
+ WCD934X_COMP_SOFT_RST_MASK, 0x0);
+ break;
+ }
+
+ return 0;
+}
+
+static int wcd934x_codec_enable_interp_clk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kc, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ int interp_idx = w->shift;
+ u16 main_reg = WCD934X_CDC_RX0_RX_PATH_CTL + (interp_idx * 20);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Clk enable */
+ snd_soc_component_update_bits(comp, main_reg,
+ WCD934X_RX_CLK_EN_MASK,
+ WCD934X_RX_CLK_ENABLE);
+ wcd934x_codec_hd2_control(comp, interp_idx, event);
+ wcd934x_codec_hphdelay_lutbypass(comp, interp_idx, event);
+ wcd934x_config_compander(comp, interp_idx, event);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ wcd934x_config_compander(comp, interp_idx, event);
+ wcd934x_codec_hphdelay_lutbypass(comp, interp_idx, event);
+ wcd934x_codec_hd2_control(comp, interp_idx, event);
+ /* Clk Disable */
+ snd_soc_component_update_bits(comp, main_reg,
+ WCD934X_RX_CLK_EN_MASK, 0);
+ /* Reset enable and disable */
+ snd_soc_component_update_bits(comp, main_reg,
+ WCD934X_RX_RESET_MASK,
+ WCD934X_RX_RESET_ENABLE);
+ snd_soc_component_update_bits(comp, main_reg,
+ WCD934X_RX_RESET_MASK,
+ WCD934X_RX_RESET_DISABLE);
+ /* Reset rate to 48K*/
+ snd_soc_component_update_bits(comp, main_reg,
+ WCD934X_RX_PCM_RATE_MASK,
+ WCD934X_RX_PCM_RATE_F_48K);
+ break;
+ }
+
+ return 0;
+}
+
+static int wcd934x_codec_enable_mix_path(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kc, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ int offset_val = 0;
+ u16 gain_reg, mix_reg;
+ int val = 0;
+
+ gain_reg = WCD934X_CDC_RX0_RX_VOL_MIX_CTL +
+ (w->shift * WCD934X_RX_PATH_CTL_OFFSET);
+ mix_reg = WCD934X_CDC_RX0_RX_PATH_MIX_CTL +
+ (w->shift * WCD934X_RX_PATH_CTL_OFFSET);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Clk enable */
+ snd_soc_component_update_bits(comp, mix_reg,
+ WCD934X_CDC_RX_MIX_CLK_EN_MASK,
+ WCD934X_CDC_RX_MIX_CLK_ENABLE);
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+ val = snd_soc_component_read32(comp, gain_reg);
+ val += offset_val;
+ snd_soc_component_write(comp, gain_reg, val);
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_set_iir_gain(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ int reg = w->reg;
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /* B1 GAIN */
+ snd_soc_component_write(comp, reg,
+ snd_soc_component_read32(comp, reg));
+ /* B2 GAIN */
+ reg++;
+ snd_soc_component_write(comp, reg,
+ snd_soc_component_read32(comp, reg));
+ /* B3 GAIN */
+ reg++;
+ snd_soc_component_write(comp, reg,
+ snd_soc_component_read32(comp, reg));
+ /* B4 GAIN */
+ reg++;
+ snd_soc_component_write(comp, reg,
+ snd_soc_component_read32(comp, reg));
+ /* B5 GAIN */
+ reg++;
+ snd_soc_component_write(comp, reg,
+ snd_soc_component_read32(comp, reg));
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int wcd934x_codec_enable_main_path(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ u16 gain_reg;
+
+ gain_reg = WCD934X_CDC_RX0_RX_VOL_CTL + (w->shift *
+ WCD934X_RX_PATH_CTL_OFFSET);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_component_write(comp, gain_reg,
+ snd_soc_component_read32(comp, gain_reg));
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_ear_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kc, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Disable AutoChop timer during power up */
+ snd_soc_component_update_bits(comp,
+ WCD934X_HPH_NEW_INT_HPH_TIMER1,
+ WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK, 0x0);
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_PRE_DAC,
+ WCD_CLSH_STATE_EAR, CLS_H_NORMAL);
+
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_POST_PA,
+ WCD_CLSH_STATE_EAR, CLS_H_NORMAL);
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+ int hph_mode = wcd->hph_mode;
+ u8 dem_inp;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Read DEM INP Select */
+ dem_inp = snd_soc_component_read32(comp,
+ WCD934X_CDC_RX1_RX_PATH_SEC0) & 0x03;
+
+ if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) ||
+ (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) {
+ return -EINVAL;
+ }
+ if (hph_mode != CLS_H_LP)
+ /* Ripple freq control enable */
+ snd_soc_component_update_bits(comp,
+ WCD934X_SIDO_NEW_VOUT_D_FREQ2,
+ WCD934X_SIDO_RIPPLE_FREQ_EN_MASK,
+ WCD934X_SIDO_RIPPLE_FREQ_ENABLE);
+ /* Disable AutoChop timer during power up */
+ snd_soc_component_update_bits(comp,
+ WCD934X_HPH_NEW_INT_HPH_TIMER1,
+ WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK, 0x0);
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_PRE_DAC,
+ WCD_CLSH_STATE_HPHL, hph_mode);
+
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* 1000us required as per HW requirement */
+ usleep_range(1000, 1100);
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_POST_PA,
+ WCD_CLSH_STATE_HPHL, hph_mode);
+ if (hph_mode != CLS_H_LP)
+ /* Ripple freq control disable */
+ snd_soc_component_update_bits(comp,
+ WCD934X_SIDO_NEW_VOUT_D_FREQ2,
+ WCD934X_SIDO_RIPPLE_FREQ_EN_MASK, 0x0);
+
+ break;
+ default:
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+ int hph_mode = wcd->hph_mode;
+ u8 dem_inp;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ dem_inp = snd_soc_component_read32(comp,
+ WCD934X_CDC_RX2_RX_PATH_SEC0) & 0x03;
+ if (((hph_mode == CLS_H_HIFI) || (hph_mode == CLS_H_LOHIFI) ||
+ (hph_mode == CLS_H_LP)) && (dem_inp != 0x01)) {
+ return -EINVAL;
+ }
+ if (hph_mode != CLS_H_LP)
+ /* Ripple freq control enable */
+ snd_soc_component_update_bits(comp,
+ WCD934X_SIDO_NEW_VOUT_D_FREQ2,
+ WCD934X_SIDO_RIPPLE_FREQ_EN_MASK,
+ WCD934X_SIDO_RIPPLE_FREQ_ENABLE);
+ /* Disable AutoChop timer during power up */
+ snd_soc_component_update_bits(comp,
+ WCD934X_HPH_NEW_INT_HPH_TIMER1,
+ WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK, 0x0);
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_PRE_DAC,
+ WCD_CLSH_STATE_HPHR,
+ hph_mode);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* 1000us required as per HW requirement */
+ usleep_range(1000, 1100);
+
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_POST_PA,
+ WCD_CLSH_STATE_HPHR, hph_mode);
+ if (hph_mode != CLS_H_LP)
+ /* Ripple freq control disable */
+ snd_soc_component_update_bits(comp,
+ WCD934X_SIDO_NEW_VOUT_D_FREQ2,
+ WCD934X_SIDO_RIPPLE_FREQ_EN_MASK, 0x0);
+ break;
+ default:
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_lineout_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kc, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_PRE_DAC,
+ WCD_CLSH_STATE_LO, CLS_AB);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ wcd_clsh_ctrl_set_state(wcd->clsh_ctrl, WCD_CLSH_EVENT_POST_PA,
+ WCD_CLSH_STATE_LO, CLS_AB);
+ break;
+ }
+
+ return 0;
+}
+
+static int wcd934x_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /*
+ * 7ms sleep is required after PA is enabled as per
+ * HW requirement. If compander is disabled, then
+ * 20ms delay is needed.
+ */
+ usleep_range(20000, 20100);
+
+ snd_soc_component_update_bits(comp, WCD934X_HPH_L_TEST,
+ WCD934X_HPH_OCP_DET_MASK,
+ WCD934X_HPH_OCP_DET_ENABLE);
+ /* Remove Mute on primary path */
+ snd_soc_component_update_bits(comp, WCD934X_CDC_RX1_RX_PATH_CTL,
+ WCD934X_RX_PATH_PGA_MUTE_EN_MASK,
+ 0);
+ /* Enable GM3 boost */
+ snd_soc_component_update_bits(comp, WCD934X_HPH_CNP_WG_CTL,
+ WCD934X_HPH_GM3_BOOST_EN_MASK,
+ WCD934X_HPH_GM3_BOOST_ENABLE);
+ /* Enable AutoChop timer at the end of power up */
+ snd_soc_component_update_bits(comp,
+ WCD934X_HPH_NEW_INT_HPH_TIMER1,
+ WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK,
+ WCD934X_HPH_AUTOCHOP_TIMER_ENABLE);
+ /* Remove mix path mute */
+ snd_soc_component_update_bits(comp,
+ WCD934X_CDC_RX1_RX_PATH_MIX_CTL,
+ WCD934X_CDC_RX_PGA_MUTE_EN_MASK, 0x00);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ /* Enable DSD Mute before PA disable */
+ snd_soc_component_update_bits(comp, WCD934X_HPH_L_TEST,
+ WCD934X_HPH_OCP_DET_MASK,
+ WCD934X_HPH_OCP_DET_DISABLE);
+ snd_soc_component_update_bits(comp, WCD934X_CDC_RX1_RX_PATH_CTL,
+ WCD934X_RX_PATH_PGA_MUTE_EN_MASK,
+ WCD934X_RX_PATH_PGA_MUTE_ENABLE);
+ snd_soc_component_update_bits(comp,
+ WCD934X_CDC_RX1_RX_PATH_MIX_CTL,
+ WCD934X_RX_PATH_PGA_MUTE_EN_MASK,
+ WCD934X_RX_PATH_PGA_MUTE_ENABLE);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /*
+ * 5ms sleep is required after PA disable. If compander is
+ * disabled, then 20ms delay is needed after PA disable.
+ */
+ usleep_range(20000, 20100);
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ /*
+ * 7ms sleep is required after PA is enabled as per
+ * HW requirement. If compander is disabled, then
+ * 20ms delay is needed.
+ */
+ usleep_range(20000, 20100);
+ snd_soc_component_update_bits(comp, WCD934X_HPH_R_TEST,
+ WCD934X_HPH_OCP_DET_MASK,
+ WCD934X_HPH_OCP_DET_ENABLE);
+ /* Remove mute */
+ snd_soc_component_update_bits(comp, WCD934X_CDC_RX2_RX_PATH_CTL,
+ WCD934X_RX_PATH_PGA_MUTE_EN_MASK,
+ 0);
+ /* Enable GM3 boost */
+ snd_soc_component_update_bits(comp, WCD934X_HPH_CNP_WG_CTL,
+ WCD934X_HPH_GM3_BOOST_EN_MASK,
+ WCD934X_HPH_GM3_BOOST_ENABLE);
+ /* Enable AutoChop timer at the end of power up */
+ snd_soc_component_update_bits(comp,
+ WCD934X_HPH_NEW_INT_HPH_TIMER1,
+ WCD934X_HPH_AUTOCHOP_TIMER_EN_MASK,
+ WCD934X_HPH_AUTOCHOP_TIMER_ENABLE);
+ /* Remove mix path mute if it is enabled */
+ if ((snd_soc_component_read32(comp,
+ WCD934X_CDC_RX2_RX_PATH_MIX_CTL)) & 0x10)
+ snd_soc_component_update_bits(comp,
+ WCD934X_CDC_RX2_RX_PATH_MIX_CTL,
+ WCD934X_CDC_RX_PGA_MUTE_EN_MASK,
+ WCD934X_CDC_RX_PGA_MUTE_DISABLE);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_component_update_bits(comp, WCD934X_HPH_R_TEST,
+ WCD934X_HPH_OCP_DET_MASK,
+ WCD934X_HPH_OCP_DET_DISABLE);
+ snd_soc_component_update_bits(comp, WCD934X_CDC_RX2_RX_PATH_CTL,
+ WCD934X_RX_PATH_PGA_MUTE_EN_MASK,
+ WCD934X_RX_PATH_PGA_MUTE_ENABLE);
+ snd_soc_component_update_bits(comp,
+ WCD934X_CDC_RX2_RX_PATH_MIX_CTL,
+ WCD934X_CDC_RX_PGA_MUTE_EN_MASK,
+ WCD934X_CDC_RX_PGA_MUTE_ENABLE);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /*
+ * 5ms sleep is required after PA disable. If compander is
+ * disabled, then 20ms delay is needed after PA disable.
+ */
+ usleep_range(20000, 20100);
+ break;
+ };
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget wcd934x_dapm_widgets[] = {
+ /* Analog Outputs */
+ SND_SOC_DAPM_OUTPUT("EAR"),
+ SND_SOC_DAPM_OUTPUT("HPHL"),
+ SND_SOC_DAPM_OUTPUT("HPHR"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+ SND_SOC_DAPM_OUTPUT("SPK1 OUT"),
+ SND_SOC_DAPM_OUTPUT("SPK2 OUT"),
+ SND_SOC_DAPM_OUTPUT("ANC EAR"),
+ SND_SOC_DAPM_OUTPUT("ANC HPHL"),
+ SND_SOC_DAPM_OUTPUT("ANC HPHR"),
+ SND_SOC_DAPM_OUTPUT("WDMA3_OUT"),
+ SND_SOC_DAPM_OUTPUT("MAD_CPE_OUT1"),
+ SND_SOC_DAPM_OUTPUT("MAD_CPE_OUT2"),
+ SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
+ AIF1_PB, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("AIF2 PB", "AIF2 Playback", 0, SND_SOC_NOPM,
+ AIF2_PB, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("AIF3 PB", "AIF3 Playback", 0, SND_SOC_NOPM,
+ AIF3_PB, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("AIF4 PB", "AIF4 Playback", 0, SND_SOC_NOPM,
+ AIF4_PB, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM RX0 MUX", SND_SOC_NOPM, WCD934X_RX0, 0,
+ &slim_rx_mux[WCD934X_RX0]),
+ SND_SOC_DAPM_MUX("SLIM RX1 MUX", SND_SOC_NOPM, WCD934X_RX1, 0,
+ &slim_rx_mux[WCD934X_RX1]),
+ SND_SOC_DAPM_MUX("SLIM RX2 MUX", SND_SOC_NOPM, WCD934X_RX2, 0,
+ &slim_rx_mux[WCD934X_RX2]),
+ SND_SOC_DAPM_MUX("SLIM RX3 MUX", SND_SOC_NOPM, WCD934X_RX3, 0,
+ &slim_rx_mux[WCD934X_RX3]),
+ SND_SOC_DAPM_MUX("SLIM RX4 MUX", SND_SOC_NOPM, WCD934X_RX4, 0,
+ &slim_rx_mux[WCD934X_RX4]),
+ SND_SOC_DAPM_MUX("SLIM RX5 MUX", SND_SOC_NOPM, WCD934X_RX5, 0,
+ &slim_rx_mux[WCD934X_RX5]),
+ SND_SOC_DAPM_MUX("SLIM RX6 MUX", SND_SOC_NOPM, WCD934X_RX6, 0,
+ &slim_rx_mux[WCD934X_RX6]),
+ SND_SOC_DAPM_MUX("SLIM RX7 MUX", SND_SOC_NOPM, WCD934X_RX7, 0,
+ &slim_rx_mux[WCD934X_RX7]),
+
+ SND_SOC_DAPM_MIXER("SLIM RX0", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX6", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM RX7", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX_E("RX INT0_2 MUX", SND_SOC_NOPM, INTERP_EAR, 0,
+ &rx_int0_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT1_2 MUX", SND_SOC_NOPM, INTERP_HPHL, 0,
+ &rx_int1_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT2_2 MUX", SND_SOC_NOPM, INTERP_HPHR, 0,
+ &rx_int2_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT3_2 MUX", SND_SOC_NOPM, INTERP_LO1, 0,
+ &rx_int3_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT4_2 MUX", SND_SOC_NOPM, INTERP_LO2, 0,
+ &rx_int4_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT7_2 MUX", SND_SOC_NOPM, INTERP_SPKR1, 0,
+ &rx_int7_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT8_2 MUX", SND_SOC_NOPM, INTERP_SPKR2, 0,
+ &rx_int8_2_mux, wcd934x_codec_enable_mix_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int0_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int0_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT0_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int0_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int1_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int1_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT1_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int1_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int2_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int2_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT2_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int2_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT3_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int3_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT3_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int3_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT3_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int3_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT4_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int4_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT4_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int4_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT4_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int4_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT7_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int7_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT7_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int7_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT7_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int7_1_mix_inp2_mux),
+ SND_SOC_DAPM_MUX("RX INT8_1 MIX1 INP0", SND_SOC_NOPM, 0, 0,
+ &rx_int8_1_mix_inp0_mux),
+ SND_SOC_DAPM_MUX("RX INT8_1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_int8_1_mix_inp1_mux),
+ SND_SOC_DAPM_MUX("RX INT8_1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_int8_1_mix_inp2_mux),
+ SND_SOC_DAPM_MIXER("RX INT0_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT1_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT1 SEC MIX", SND_SOC_NOPM, 0, 0,
+ rx_int1_asrc_switch,
+ ARRAY_SIZE(rx_int1_asrc_switch)),
+ SND_SOC_DAPM_MIXER("RX INT2_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT2 SEC MIX", SND_SOC_NOPM, 0, 0,
+ rx_int2_asrc_switch,
+ ARRAY_SIZE(rx_int2_asrc_switch)),
+ SND_SOC_DAPM_MIXER("RX INT3_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT3 SEC MIX", SND_SOC_NOPM, 0, 0,
+ rx_int3_asrc_switch,
+ ARRAY_SIZE(rx_int3_asrc_switch)),
+ SND_SOC_DAPM_MIXER("RX INT4_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT4 SEC MIX", SND_SOC_NOPM, 0, 0,
+ rx_int4_asrc_switch,
+ ARRAY_SIZE(rx_int4_asrc_switch)),
+ SND_SOC_DAPM_MIXER("RX INT7_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT7 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT8_1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT8 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT0 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT1 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT1 MIX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT2 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT2 MIX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT3 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT3 MIX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT4 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX INT4 MIX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER("RX INT7 MIX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER_E("RX INT7 CHAIN", SND_SOC_NOPM, 0, 0,
+ NULL, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER_E("RX INT8 CHAIN", SND_SOC_NOPM, 0, 0,
+ NULL, 0, NULL, 0),
+ SND_SOC_DAPM_MUX_E("RX INT0 MIX2 INP", WCD934X_CDC_RX0_RX_PATH_CFG0, 4,
+ 0, &rx_int0_mix2_inp_mux, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT1 MIX2 INP", WCD934X_CDC_RX1_RX_PATH_CFG0, 4,
+ 0, &rx_int1_mix2_inp_mux, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT2 MIX2 INP", WCD934X_CDC_RX2_RX_PATH_CFG0, 4,
+ 0, &rx_int2_mix2_inp_mux, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT3 MIX2 INP", WCD934X_CDC_RX3_RX_PATH_CFG0, 4,
+ 0, &rx_int3_mix2_inp_mux, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT4 MIX2 INP", WCD934X_CDC_RX4_RX_PATH_CFG0, 4,
+ 0, &rx_int4_mix2_inp_mux, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT7 MIX2 INP", WCD934X_CDC_RX7_RX_PATH_CFG0, 4,
+ 0, &rx_int7_mix2_inp_mux, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("IIR0 INP0 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp0_mux),
+ SND_SOC_DAPM_MUX("IIR0 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp1_mux),
+ SND_SOC_DAPM_MUX("IIR0 INP2 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp2_mux),
+ SND_SOC_DAPM_MUX("IIR0 INP3 MUX", SND_SOC_NOPM, 0, 0, &iir0_inp3_mux),
+ SND_SOC_DAPM_MUX("IIR1 INP0 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp0_mux),
+ SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+ SND_SOC_DAPM_MUX("IIR1 INP2 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp2_mux),
+ SND_SOC_DAPM_MUX("IIR1 INP3 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp3_mux),
+
+ SND_SOC_DAPM_PGA_E("IIR0", WCD934X_CDC_SIDETONE_IIR0_IIR_GAIN_B1_CTL,
+ 0, 0, NULL, 0, wcd934x_codec_set_iir_gain,
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_E("IIR1", WCD934X_CDC_SIDETONE_IIR1_IIR_GAIN_B1_CTL,
+ 1, 0, NULL, 0, wcd934x_codec_set_iir_gain,
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MIXER("SRC0", WCD934X_CDC_SIDETONE_SRC0_ST_SRC_PATH_CTL,
+ 4, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SRC1", WCD934X_CDC_SIDETONE_SRC1_ST_SRC_PATH_CTL,
+ 4, 0, NULL, 0),
+ SND_SOC_DAPM_MUX("RX INT0 DEM MUX", SND_SOC_NOPM, 0, 0,
+ &rx_int0_dem_inp_mux),
+ SND_SOC_DAPM_MUX("RX INT1 DEM MUX", SND_SOC_NOPM, 0, 0,
+ &rx_int1_dem_inp_mux),
+ SND_SOC_DAPM_MUX("RX INT2 DEM MUX", SND_SOC_NOPM, 0, 0,
+ &rx_int2_dem_inp_mux),
+
+ SND_SOC_DAPM_MUX_E("RX INT0_1 INTERP", SND_SOC_NOPM, INTERP_EAR, 0,
+ &rx_int0_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT1_1 INTERP", SND_SOC_NOPM, INTERP_HPHL, 0,
+ &rx_int1_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT2_1 INTERP", SND_SOC_NOPM, INTERP_HPHR, 0,
+ &rx_int2_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT3_1 INTERP", SND_SOC_NOPM, INTERP_LO1, 0,
+ &rx_int3_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT4_1 INTERP", SND_SOC_NOPM, INTERP_LO2, 0,
+ &rx_int4_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT7_1 INTERP", SND_SOC_NOPM, INTERP_SPKR1, 0,
+ &rx_int7_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT8_1 INTERP", SND_SOC_NOPM, INTERP_SPKR2, 0,
+ &rx_int8_1_interp_mux,
+ wcd934x_codec_enable_main_path,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("RX INT0_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int0_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT1_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int1_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT2_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int2_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT3_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int3_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT4_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int4_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT7_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int7_2_interp_mux),
+ SND_SOC_DAPM_MUX("RX INT8_2 INTERP", SND_SOC_NOPM, 0, 0,
+ &rx_int8_2_interp_mux),
+ SND_SOC_DAPM_DAC_E("RX INT0 DAC", NULL, SND_SOC_NOPM,
+ 0, 0, wcd934x_codec_ear_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("RX INT1 DAC", NULL, WCD934X_ANA_HPH,
+ 5, 0, wcd934x_codec_hphl_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("RX INT2 DAC", NULL, WCD934X_ANA_HPH,
+ 4, 0, wcd934x_codec_hphr_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("RX INT3 DAC", NULL, SND_SOC_NOPM,
+ 0, 0, wcd934x_codec_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("RX INT4 DAC", NULL, SND_SOC_NOPM,
+ 0, 0, wcd934x_codec_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("EAR PA", WCD934X_ANA_EAR, 7, 0, NULL, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_E("HPHL PA", WCD934X_ANA_HPH, 7, 0, NULL, 0,
+ wcd934x_codec_enable_hphl_pa,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("HPHR PA", WCD934X_ANA_HPH, 6, 0, NULL, 0,
+ wcd934x_codec_enable_hphr_pa,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("LINEOUT1 PA", WCD934X_ANA_LO_1_2, 7, 0, NULL, 0,
+ NULL, 0),
+ SND_SOC_DAPM_PGA_E("LINEOUT2 PA", WCD934X_ANA_LO_1_2, 6, 0, NULL, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("RX_BIAS", WCD934X_ANA_RX_SUPPLIES, 0, 0, NULL,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("SBOOST0", WCD934X_CDC_RX7_RX_PATH_CFG1,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SBOOST0_CLK", WCD934X_CDC_BOOST0_BOOST_PATH_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SBOOST1", WCD934X_CDC_RX8_RX_PATH_CFG1,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SBOOST1_CLK", WCD934X_CDC_BOOST1_BOOST_PATH_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("INT0_CLK", SND_SOC_NOPM, INTERP_EAR, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("INT1_CLK", SND_SOC_NOPM, INTERP_HPHL, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("INT2_CLK", SND_SOC_NOPM, INTERP_HPHR, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("INT3_CLK", SND_SOC_NOPM, INTERP_LO1, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("INT4_CLK", SND_SOC_NOPM, INTERP_LO2, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("INT7_CLK", SND_SOC_NOPM, INTERP_SPKR1, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("INT8_CLK", SND_SOC_NOPM, INTERP_SPKR2, 0,
+ wcd934x_codec_enable_interp_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("DSMDEM0_CLK", WCD934X_CDC_RX0_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DSMDEM1_CLK", WCD934X_CDC_RX1_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DSMDEM2_CLK", WCD934X_CDC_RX2_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DSMDEM3_CLK", WCD934X_CDC_RX3_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DSMDEM4_CLK", WCD934X_CDC_RX4_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DSMDEM7_CLK", WCD934X_CDC_RX7_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DSMDEM8_CLK", WCD934X_CDC_RX8_RX_PATH_DSMDEM_CTL,
+ 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_mclk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+};
+
static const struct snd_soc_component_driver wcd934x_component_drv = {
.probe = wcd934x_comp_probe,
.remove = wcd934x_comp_remove,
.set_sysclk = wcd934x_comp_set_sysclk,
.controls = wcd934x_snd_controls,
.num_controls = ARRAY_SIZE(wcd934x_snd_controls),
+ .dapm_widgets = wcd934x_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wcd934x_dapm_widgets),
};
static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd)
--
2.20.1
1
0
[alsa-devel] Applied "ASoC: wcd934x: add capture dapm widgets" to the asoc tree
by Mark Brown 25 Dec '19
by Mark Brown 25 Dec '19
25 Dec '19
The patch
ASoC: wcd934x: add capture dapm widgets
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From a70d9245759a48e57bb1dc9f63213dcf3017db32 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Date: Thu, 19 Dec 2019 10:31:48 +0000
Subject: [PATCH] ASoC: wcd934x: add capture dapm widgets
This patch adds required dapm widgets for capture path.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Link: https://lore.kernel.org/r/20191219103153.14875-7-srinivas.kandagatla@linaro…
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart(a)linux.intel.com>
Signed-off-by: Mark Brown <broonie(a)kernel.org>
---
sound/soc/codecs/wcd934x.c | 1151 +++++++++++++++++++++++++++++++++++-
1 file changed, 1149 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index 556c051f7f99..24f78a0b7f5a 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -135,6 +135,13 @@
} \
}
+enum {
+ MIC_BIAS_1 = 1,
+ MIC_BIAS_2,
+ MIC_BIAS_3,
+ MIC_BIAS_4
+};
+
enum {
SIDO_SOURCE_INTERNAL,
SIDO_SOURCE_RCO_BG,
@@ -500,6 +507,83 @@ static const char * const rx_int8_2_interp_mux_text[] = {
"ZERO", "RX INT8_2 MUX",
};
+static const char * const dmic_mux_text[] = {
+ "ZERO", "DMIC0", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5"
+};
+
+static const char * const amic_mux_text[] = {
+ "ZERO", "ADC1", "ADC2", "ADC3", "ADC4"
+};
+
+static const char * const amic4_5_sel_text[] = {
+ "AMIC4", "AMIC5"
+};
+
+static const char * const adc_mux_text[] = {
+ "DMIC", "AMIC", "ANC_FB_TUNE1", "ANC_FB_TUNE2"
+};
+
+static const char * const cdc_if_tx0_mux_text[] = {
+ "ZERO", "RX_MIX_TX0", "DEC0", "DEC0_192"
+};
+
+static const char * const cdc_if_tx1_mux_text[] = {
+ "ZERO", "RX_MIX_TX1", "DEC1", "DEC1_192"
+};
+
+static const char * const cdc_if_tx2_mux_text[] = {
+ "ZERO", "RX_MIX_TX2", "DEC2", "DEC2_192"
+};
+
+static const char * const cdc_if_tx3_mux_text[] = {
+ "ZERO", "RX_MIX_TX3", "DEC3", "DEC3_192"
+};
+
+static const char * const cdc_if_tx4_mux_text[] = {
+ "ZERO", "RX_MIX_TX4", "DEC4", "DEC4_192"
+};
+
+static const char * const cdc_if_tx5_mux_text[] = {
+ "ZERO", "RX_MIX_TX5", "DEC5", "DEC5_192"
+};
+
+static const char * const cdc_if_tx6_mux_text[] = {
+ "ZERO", "RX_MIX_TX6", "DEC6", "DEC6_192"
+};
+
+static const char * const cdc_if_tx7_mux_text[] = {
+ "ZERO", "RX_MIX_TX7", "DEC7", "DEC7_192"
+};
+
+static const char * const cdc_if_tx8_mux_text[] = {
+ "ZERO", "RX_MIX_TX8", "DEC8", "DEC8_192"
+};
+
+static const char * const cdc_if_tx9_mux_text[] = {
+ "ZERO", "DEC7", "DEC7_192"
+};
+
+static const char * const cdc_if_tx10_mux_text[] = {
+ "ZERO", "DEC6", "DEC6_192"
+};
+
+static const char * const cdc_if_tx11_mux_text[] = {
+ "DEC_0_5", "DEC_9_12", "MAD_AUDIO", "MAD_BRDCST"
+};
+
+static const char * const cdc_if_tx11_inp1_mux_text[] = {
+ "ZERO", "DEC0", "DEC1", "DEC2", "DEC3", "DEC4",
+ "DEC5", "RX_MIX_TX5", "DEC9_10", "DEC11_12"
+};
+
+static const char * const cdc_if_tx13_mux_text[] = {
+ "CDC_DEC_5", "MAD_BRDCST"
+};
+
+static const char * const cdc_if_tx13_inp1_mux_text[] = {
+ "ZERO", "DEC5", "DEC5_192"
+};
+
static const struct soc_enum cf_dec0_enum =
SOC_ENUM_SINGLE(WCD934X_CDC_TX0_TX_PATH_CFG0, 5, 3, cf_text);
@@ -758,6 +842,35 @@ static const struct soc_enum rx_int2_dem_inp_mux_enum =
SOC_ENUM_SINGLE(WCD934X_CDC_RX2_RX_PATH_SEC0, 0,
ARRAY_SIZE(rx_int_dem_inp_mux_text),
rx_int_dem_inp_mux_text);
+
+static const struct soc_enum tx_adc_mux0_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux2_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux3_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux4_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 2,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux5_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 2,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux6_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 2,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux7_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 2,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+static const struct soc_enum tx_adc_mux8_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 4,
+ ARRAY_SIZE(adc_mux_text), adc_mux_text);
+
static const struct soc_enum rx_int0_1_interp_mux_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2,
rx_int0_1_interp_mux_text);
@@ -803,8 +916,122 @@ static const struct soc_enum rx_int7_2_interp_mux_enum =
static const struct soc_enum rx_int8_2_interp_mux_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int8_2_interp_mux_text);
-static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd,
- int sido_src)
+static const struct soc_enum tx_dmic_mux0_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux2_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux3_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux4_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux5_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux6_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux7_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_dmic_mux8_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 3, 7,
+ dmic_mux_text);
+
+static const struct soc_enum tx_amic_mux0_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux1_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux2_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux3_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux4_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux5_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux6_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux7_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0, 5,
+ amic_mux_text);
+static const struct soc_enum tx_amic_mux8_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 0, 5,
+ amic_mux_text);
+
+static const struct soc_enum tx_amic4_5_enum =
+ SOC_ENUM_SINGLE(WCD934X_TX_NEW_AMIC_4_5_SEL, 7, 2, amic4_5_sel_text);
+
+static const struct soc_enum cdc_if_tx0_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 0,
+ ARRAY_SIZE(cdc_if_tx0_mux_text), cdc_if_tx0_mux_text);
+static const struct soc_enum cdc_if_tx1_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 2,
+ ARRAY_SIZE(cdc_if_tx1_mux_text), cdc_if_tx1_mux_text);
+static const struct soc_enum cdc_if_tx2_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 4,
+ ARRAY_SIZE(cdc_if_tx2_mux_text), cdc_if_tx2_mux_text);
+static const struct soc_enum cdc_if_tx3_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 6,
+ ARRAY_SIZE(cdc_if_tx3_mux_text), cdc_if_tx3_mux_text);
+static const struct soc_enum cdc_if_tx4_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 0,
+ ARRAY_SIZE(cdc_if_tx4_mux_text), cdc_if_tx4_mux_text);
+static const struct soc_enum cdc_if_tx5_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 2,
+ ARRAY_SIZE(cdc_if_tx5_mux_text), cdc_if_tx5_mux_text);
+static const struct soc_enum cdc_if_tx6_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 4,
+ ARRAY_SIZE(cdc_if_tx6_mux_text), cdc_if_tx6_mux_text);
+static const struct soc_enum cdc_if_tx7_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 6,
+ ARRAY_SIZE(cdc_if_tx7_mux_text), cdc_if_tx7_mux_text);
+static const struct soc_enum cdc_if_tx8_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 0,
+ ARRAY_SIZE(cdc_if_tx8_mux_text), cdc_if_tx8_mux_text);
+static const struct soc_enum cdc_if_tx9_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 2,
+ ARRAY_SIZE(cdc_if_tx9_mux_text), cdc_if_tx9_mux_text);
+static const struct soc_enum cdc_if_tx10_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 4,
+ ARRAY_SIZE(cdc_if_tx10_mux_text), cdc_if_tx10_mux_text);
+static const struct soc_enum cdc_if_tx11_inp1_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3, 0,
+ ARRAY_SIZE(cdc_if_tx11_inp1_mux_text),
+ cdc_if_tx11_inp1_mux_text);
+static const struct soc_enum cdc_if_tx11_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_DATA_HUB_SB_TX11_INP_CFG, 0,
+ ARRAY_SIZE(cdc_if_tx11_mux_text), cdc_if_tx11_mux_text);
+static const struct soc_enum cdc_if_tx13_inp1_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3, 4,
+ ARRAY_SIZE(cdc_if_tx13_inp1_mux_text),
+ cdc_if_tx13_inp1_mux_text);
+static const struct soc_enum cdc_if_tx13_mux_enum =
+ SOC_ENUM_SINGLE(WCD934X_DATA_HUB_SB_TX13_INP_CFG, 0,
+ ARRAY_SIZE(cdc_if_tx13_mux_text), cdc_if_tx13_mux_text);
+
+static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd, int sido_src)
{
if (sido_src == wcd->sido_input_src)
return 0;
@@ -2241,6 +2468,63 @@ static int wcd934x_int_dem_inp_mux_put(struct snd_kcontrol *kc,
return ret;
}
+static int wcd934x_dec_enum_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp;
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int val;
+ u16 mic_sel_reg = 0;
+ u8 mic_sel;
+
+ comp = snd_soc_dapm_kcontrol_component(kcontrol);
+
+ val = ucontrol->value.enumerated.item[0];
+ if (val > e->items - 1)
+ return -EINVAL;
+
+ switch (e->reg) {
+ case WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1:
+ if (e->shift_l == 0)
+ mic_sel_reg = WCD934X_CDC_TX0_TX_PATH_CFG0;
+ else if (e->shift_l == 2)
+ mic_sel_reg = WCD934X_CDC_TX4_TX_PATH_CFG0;
+ else if (e->shift_l == 4)
+ mic_sel_reg = WCD934X_CDC_TX8_TX_PATH_CFG0;
+ break;
+ case WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1:
+ if (e->shift_l == 0)
+ mic_sel_reg = WCD934X_CDC_TX1_TX_PATH_CFG0;
+ else if (e->shift_l == 2)
+ mic_sel_reg = WCD934X_CDC_TX5_TX_PATH_CFG0;
+ break;
+ case WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1:
+ if (e->shift_l == 0)
+ mic_sel_reg = WCD934X_CDC_TX2_TX_PATH_CFG0;
+ else if (e->shift_l == 2)
+ mic_sel_reg = WCD934X_CDC_TX6_TX_PATH_CFG0;
+ break;
+ case WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1:
+ if (e->shift_l == 0)
+ mic_sel_reg = WCD934X_CDC_TX3_TX_PATH_CFG0;
+ else if (e->shift_l == 2)
+ mic_sel_reg = WCD934X_CDC_TX7_TX_PATH_CFG0;
+ break;
+ default:
+ dev_err(comp->dev, "%s: e->reg: 0x%x not expected\n",
+ __func__, e->reg);
+ return -EINVAL;
+ }
+
+ /* ADC: 0, DMIC: 1 */
+ mic_sel = val ? 0x0 : 0x1;
+ if (mic_sel_reg)
+ snd_soc_component_update_bits(comp, mic_sel_reg, BIT(7),
+ mic_sel << 7);
+
+ return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+}
+
static const struct snd_kcontrol_new rx_int0_2_mux =
SOC_DAPM_ENUM("RX INT0_2 MUX Mux", rx_int0_2_mux_chain_enum);
@@ -2453,6 +2737,252 @@ static const struct snd_kcontrol_new rx_int7_2_interp_mux =
static const struct snd_kcontrol_new rx_int8_2_interp_mux =
SOC_DAPM_ENUM("RX INT8_2 INTERP Mux", rx_int8_2_interp_mux_enum);
+static const struct snd_kcontrol_new tx_dmic_mux0 =
+ SOC_DAPM_ENUM("DMIC MUX0 Mux", tx_dmic_mux0_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux1 =
+ SOC_DAPM_ENUM("DMIC MUX1 Mux", tx_dmic_mux1_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux2 =
+ SOC_DAPM_ENUM("DMIC MUX2 Mux", tx_dmic_mux2_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux3 =
+ SOC_DAPM_ENUM("DMIC MUX3 Mux", tx_dmic_mux3_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux4 =
+ SOC_DAPM_ENUM("DMIC MUX4 Mux", tx_dmic_mux4_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux5 =
+ SOC_DAPM_ENUM("DMIC MUX5 Mux", tx_dmic_mux5_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux6 =
+ SOC_DAPM_ENUM("DMIC MUX6 Mux", tx_dmic_mux6_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux7 =
+ SOC_DAPM_ENUM("DMIC MUX7 Mux", tx_dmic_mux7_enum);
+
+static const struct snd_kcontrol_new tx_dmic_mux8 =
+ SOC_DAPM_ENUM("DMIC MUX8 Mux", tx_dmic_mux8_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux0 =
+ SOC_DAPM_ENUM("AMIC MUX0 Mux", tx_amic_mux0_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux1 =
+ SOC_DAPM_ENUM("AMIC MUX1 Mux", tx_amic_mux1_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux2 =
+ SOC_DAPM_ENUM("AMIC MUX2 Mux", tx_amic_mux2_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux3 =
+ SOC_DAPM_ENUM("AMIC MUX3 Mux", tx_amic_mux3_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux4 =
+ SOC_DAPM_ENUM("AMIC MUX4 Mux", tx_amic_mux4_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux5 =
+ SOC_DAPM_ENUM("AMIC MUX5 Mux", tx_amic_mux5_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux6 =
+ SOC_DAPM_ENUM("AMIC MUX6 Mux", tx_amic_mux6_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux7 =
+ SOC_DAPM_ENUM("AMIC MUX7 Mux", tx_amic_mux7_enum);
+
+static const struct snd_kcontrol_new tx_amic_mux8 =
+ SOC_DAPM_ENUM("AMIC MUX8 Mux", tx_amic_mux8_enum);
+
+static const struct snd_kcontrol_new tx_amic4_5 =
+ SOC_DAPM_ENUM("AMIC4_5 SEL Mux", tx_amic4_5_enum);
+
+static const struct snd_kcontrol_new tx_adc_mux0_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX0 Mux", tx_adc_mux0_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux1_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX1 Mux", tx_adc_mux1_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux2_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX2 Mux", tx_adc_mux2_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux3_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX3 Mux", tx_adc_mux3_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux4_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX4 Mux", tx_adc_mux4_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux5_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX5 Mux", tx_adc_mux5_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux6_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX6 Mux", tx_adc_mux6_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux7_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX7 Mux", tx_adc_mux7_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+static const struct snd_kcontrol_new tx_adc_mux8_mux =
+ SOC_DAPM_ENUM_EXT("ADC MUX8 Mux", tx_adc_mux8_enum,
+ snd_soc_dapm_get_enum_double, wcd934x_dec_enum_put);
+
+static const struct snd_kcontrol_new cdc_if_tx0_mux =
+ SOC_DAPM_ENUM("CDC_IF TX0 MUX Mux", cdc_if_tx0_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx1_mux =
+ SOC_DAPM_ENUM("CDC_IF TX1 MUX Mux", cdc_if_tx1_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx2_mux =
+ SOC_DAPM_ENUM("CDC_IF TX2 MUX Mux", cdc_if_tx2_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx3_mux =
+ SOC_DAPM_ENUM("CDC_IF TX3 MUX Mux", cdc_if_tx3_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx4_mux =
+ SOC_DAPM_ENUM("CDC_IF TX4 MUX Mux", cdc_if_tx4_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx5_mux =
+ SOC_DAPM_ENUM("CDC_IF TX5 MUX Mux", cdc_if_tx5_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx6_mux =
+ SOC_DAPM_ENUM("CDC_IF TX6 MUX Mux", cdc_if_tx6_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx7_mux =
+ SOC_DAPM_ENUM("CDC_IF TX7 MUX Mux", cdc_if_tx7_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx8_mux =
+ SOC_DAPM_ENUM("CDC_IF TX8 MUX Mux", cdc_if_tx8_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx9_mux =
+ SOC_DAPM_ENUM("CDC_IF TX9 MUX Mux", cdc_if_tx9_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx10_mux =
+ SOC_DAPM_ENUM("CDC_IF TX10 MUX Mux", cdc_if_tx10_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx11_mux =
+ SOC_DAPM_ENUM("CDC_IF TX11 MUX Mux", cdc_if_tx11_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx11_inp1_mux =
+ SOC_DAPM_ENUM("CDC_IF TX11 INP1 MUX Mux", cdc_if_tx11_inp1_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx13_mux =
+ SOC_DAPM_ENUM("CDC_IF TX13 MUX Mux", cdc_if_tx13_mux_enum);
+static const struct snd_kcontrol_new cdc_if_tx13_inp1_mux =
+ SOC_DAPM_ENUM("CDC_IF TX13 INP1 MUX Mux", cdc_if_tx13_inp1_mux_enum);
+
+static int slim_tx_mixer_get(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kc);
+ struct wcd934x_codec *wcd = dev_get_drvdata(dapm->dev);
+ struct soc_mixer_control *mixer =
+ (struct soc_mixer_control *)kc->private_value;
+ int port_id = mixer->shift;
+
+ ucontrol->value.integer.value[0] = wcd->tx_port_value[port_id];
+
+ return 0;
+}
+
+static int slim_tx_mixer_put(struct snd_kcontrol *kc,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kc);
+ struct wcd934x_codec *wcd = dev_get_drvdata(widget->dapm->dev);
+ struct snd_soc_dapm_update *update = NULL;
+ struct soc_mixer_control *mixer =
+ (struct soc_mixer_control *)kc->private_value;
+ int enable = ucontrol->value.integer.value[0];
+ int dai_id = widget->shift;
+ int port_id = mixer->shift;
+
+ /* only add to the list if value not set */
+ if (enable == wcd->tx_port_value[port_id])
+ return 0;
+
+ wcd->tx_port_value[port_id] = enable;
+
+ if (enable)
+ list_add_tail(&wcd->tx_chs[port_id].list,
+ &wcd->dai[dai_id].slim_ch_list);
+ else
+ list_del_init(&wcd->tx_chs[port_id].list);
+
+ snd_soc_dapm_mixer_update_power(widget->dapm, kc, enable, update);
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new aif1_slim_cap_mixer[] = {
+ SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new aif2_slim_cap_mixer[] = {
+ SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+};
+
+static const struct snd_kcontrol_new aif3_slim_cap_mixer[] = {
+ SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD934X_TX0, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD934X_TX1, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD934X_TX2, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD934X_TX3, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD934X_TX4, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD934X_TX5, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD934X_TX6, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD934X_TX7, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD934X_TX8, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD934X_TX9, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD934X_TX10, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD934X_TX11, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+ SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD934X_TX13, 1, 0,
+ slim_tx_mixer_get, slim_tx_mixer_put),
+};
+
static const struct snd_kcontrol_new wcd934x_snd_controls[] = {
/* Gain Controls */
SOC_SINGLE_TLV("EAR PA Volume", WCD934X_ANA_EAR, 4, 4, 1, ear_pa_gain),
@@ -3193,6 +3723,455 @@ static int wcd934x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
return 0;
}
+static u32 wcd934x_get_dmic_sample_rate(struct snd_soc_component *comp,
+ unsigned int dmic,
+ struct wcd934x_codec *wcd)
+{
+ u8 tx_stream_fs;
+ u8 adc_mux_index = 0, adc_mux_sel = 0;
+ bool dec_found = false;
+ u16 adc_mux_ctl_reg, tx_fs_reg;
+ u32 dmic_fs;
+
+ while (dec_found == 0 && adc_mux_index < WCD934X_MAX_VALID_ADC_MUX) {
+ if (adc_mux_index < 4) {
+ adc_mux_ctl_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+ (adc_mux_index * 2);
+ } else if (adc_mux_index < WCD934X_INVALID_ADC_MUX) {
+ adc_mux_ctl_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
+ adc_mux_index - 4;
+ } else if (adc_mux_index == WCD934X_INVALID_ADC_MUX) {
+ ++adc_mux_index;
+ continue;
+ }
+ adc_mux_sel = ((snd_soc_component_read32(comp, adc_mux_ctl_reg)
+ & 0xF8) >> 3) - 1;
+
+ if (adc_mux_sel == dmic) {
+ dec_found = true;
+ break;
+ }
+
+ ++adc_mux_index;
+ }
+
+ if (dec_found && adc_mux_index <= 8) {
+ tx_fs_reg = WCD934X_CDC_TX0_TX_PATH_CTL + (16 * adc_mux_index);
+ tx_stream_fs = snd_soc_component_read32(comp, tx_fs_reg) & 0x0F;
+ if (tx_stream_fs <= 4) {
+ if (wcd->dmic_sample_rate <=
+ WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ)
+ dmic_fs = wcd->dmic_sample_rate;
+ else
+ dmic_fs = WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ;
+ } else
+ dmic_fs = WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
+ } else {
+ dmic_fs = wcd->dmic_sample_rate;
+ }
+
+ return dmic_fs;
+}
+
+static u8 wcd934x_get_dmic_clk_val(struct snd_soc_component *comp,
+ u32 mclk_rate, u32 dmic_clk_rate)
+{
+ u32 div_factor;
+ u8 dmic_ctl_val;
+
+ /* Default value to return in case of error */
+ if (mclk_rate == WCD934X_MCLK_CLK_9P6MHZ)
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_2;
+ else
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_3;
+
+ if (dmic_clk_rate == 0) {
+ dev_err(comp->dev,
+ "%s: dmic_sample_rate cannot be 0\n",
+ __func__);
+ goto done;
+ }
+
+ div_factor = mclk_rate / dmic_clk_rate;
+ switch (div_factor) {
+ case 2:
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_2;
+ break;
+ case 3:
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_3;
+ break;
+ case 4:
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_4;
+ break;
+ case 6:
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_6;
+ break;
+ case 8:
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_8;
+ break;
+ case 16:
+ dmic_ctl_val = WCD934X_DMIC_CLK_DIV_16;
+ break;
+ default:
+ dev_err(comp->dev,
+ "%s: Invalid div_factor %u, clk_rate(%u), dmic_rate(%u)\n",
+ __func__, div_factor, mclk_rate, dmic_clk_rate);
+ break;
+ }
+
+done:
+ return dmic_ctl_val;
+}
+
+static int wcd934x_codec_enable_dmic(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
+ u8 dmic_clk_en = 0x01;
+ u16 dmic_clk_reg;
+ s32 *dmic_clk_cnt;
+ u8 dmic_rate_val, dmic_rate_shift = 1;
+ unsigned int dmic;
+ u32 dmic_sample_rate;
+ int ret;
+ char *wname;
+
+ wname = strpbrk(w->name, "012345");
+ if (!wname) {
+ dev_err(comp->dev, "%s: widget not found\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = kstrtouint(wname, 10, &dmic);
+ if (ret < 0) {
+ dev_err(comp->dev, "%s: Invalid DMIC line on the codec\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ switch (dmic) {
+ case 0:
+ case 1:
+ dmic_clk_cnt = &wcd->dmic_0_1_clk_cnt;
+ dmic_clk_reg = WCD934X_CPE_SS_DMIC0_CTL;
+ break;
+ case 2:
+ case 3:
+ dmic_clk_cnt = &wcd->dmic_2_3_clk_cnt;
+ dmic_clk_reg = WCD934X_CPE_SS_DMIC1_CTL;
+ break;
+ case 4:
+ case 5:
+ dmic_clk_cnt = &wcd->dmic_4_5_clk_cnt;
+ dmic_clk_reg = WCD934X_CPE_SS_DMIC2_CTL;
+ break;
+ default:
+ dev_err(comp->dev, "%s: Invalid DMIC Selection\n",
+ __func__);
+ return -EINVAL;
+ };
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ dmic_sample_rate = wcd934x_get_dmic_sample_rate(comp, dmic,
+ wcd);
+ dmic_rate_val = wcd934x_get_dmic_clk_val(comp, wcd->rate,
+ dmic_sample_rate);
+ (*dmic_clk_cnt)++;
+ if (*dmic_clk_cnt == 1) {
+ dmic_rate_val = dmic_rate_val << dmic_rate_shift;
+ snd_soc_component_update_bits(comp, dmic_clk_reg,
+ WCD934X_DMIC_RATE_MASK,
+ dmic_rate_val);
+ snd_soc_component_update_bits(comp, dmic_clk_reg,
+ dmic_clk_en, dmic_clk_en);
+ }
+
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ (*dmic_clk_cnt)--;
+ if (*dmic_clk_cnt == 0)
+ snd_soc_component_update_bits(comp, dmic_clk_reg,
+ dmic_clk_en, 0);
+ break;
+ };
+
+ return 0;
+}
+
+static int wcd934x_codec_find_amic_input(struct snd_soc_component *comp,
+ int adc_mux_n)
+{
+ u16 mask, shift, adc_mux_in_reg;
+ u16 amic_mux_sel_reg;
+ bool is_amic;
+
+ if (adc_mux_n < 0 || adc_mux_n > WCD934X_MAX_VALID_ADC_MUX ||
+ adc_mux_n == WCD934X_INVALID_ADC_MUX)
+ return 0;
+
+ if (adc_mux_n < 3) {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+ adc_mux_n;
+ mask = 0x03;
+ shift = 0;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+ 2 * adc_mux_n;
+ } else if (adc_mux_n < 4) {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
+ mask = 0x03;
+ shift = 0;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0 +
+ 2 * adc_mux_n;
+ } else if (adc_mux_n < 7) {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+ (adc_mux_n - 4);
+ mask = 0x0C;
+ shift = 2;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
+ adc_mux_n - 4;
+ } else if (adc_mux_n < 8) {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
+ mask = 0x0C;
+ shift = 2;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
+ adc_mux_n - 4;
+ } else if (adc_mux_n < 12) {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
+ ((adc_mux_n == 8) ? (adc_mux_n - 8) :
+ (adc_mux_n - 9));
+ mask = 0x30;
+ shift = 4;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
+ adc_mux_n - 4;
+ } else if (adc_mux_n < 13) {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1;
+ mask = 0x30;
+ shift = 4;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
+ adc_mux_n - 4;
+ } else {
+ adc_mux_in_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1;
+ mask = 0xC0;
+ shift = 6;
+ amic_mux_sel_reg = WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0 +
+ adc_mux_n - 4;
+ }
+
+ is_amic = (((snd_soc_component_read32(comp, adc_mux_in_reg)
+ & mask) >> shift) == 1);
+ if (!is_amic)
+ return 0;
+
+ return snd_soc_component_read32(comp, amic_mux_sel_reg) & 0x07;
+}
+
+static u16 wcd934x_codec_get_amic_pwlvl_reg(struct snd_soc_component *comp,
+ int amic)
+{
+ u16 pwr_level_reg = 0;
+
+ switch (amic) {
+ case 1:
+ case 2:
+ pwr_level_reg = WCD934X_ANA_AMIC1;
+ break;
+
+ case 3:
+ case 4:
+ pwr_level_reg = WCD934X_ANA_AMIC3;
+ break;
+ default:
+ break;
+ }
+
+ return pwr_level_reg;
+}
+
+static int wcd934x_codec_enable_dec(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ unsigned int decimator;
+ char *dec_adc_mux_name = NULL;
+ char *widget_name = NULL;
+ char *wname;
+ int ret = 0, amic_n;
+ u16 tx_vol_ctl_reg, pwr_level_reg = 0, dec_cfg_reg, hpf_gate_reg;
+ u16 tx_gain_ctl_reg;
+ char *dec;
+ u8 hpf_coff_freq;
+
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name)
+ return -ENOMEM;
+
+ wname = widget_name;
+ dec_adc_mux_name = strsep(&widget_name, " ");
+ if (!dec_adc_mux_name) {
+ dev_err(comp->dev, "%s: Invalid decimator = %s\n",
+ __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ dec_adc_mux_name = widget_name;
+
+ dec = strpbrk(dec_adc_mux_name, "012345678");
+ if (!dec) {
+ dev_err(comp->dev, "%s: decimator index not found\n",
+ __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(dec, 10, &decimator);
+ if (ret < 0) {
+ dev_err(comp->dev, "%s: Invalid decimator = %s\n",
+ __func__, wname);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ tx_vol_ctl_reg = WCD934X_CDC_TX0_TX_PATH_CTL + 16 * decimator;
+ hpf_gate_reg = WCD934X_CDC_TX0_TX_PATH_SEC2 + 16 * decimator;
+ dec_cfg_reg = WCD934X_CDC_TX0_TX_PATH_CFG0 + 16 * decimator;
+ tx_gain_ctl_reg = WCD934X_CDC_TX0_TX_VOL_CTL + 16 * decimator;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ amic_n = wcd934x_codec_find_amic_input(comp, decimator);
+ if (amic_n)
+ pwr_level_reg = wcd934x_codec_get_amic_pwlvl_reg(comp,
+ amic_n);
+
+ if (!pwr_level_reg)
+ break;
+
+ switch ((snd_soc_component_read32(comp, pwr_level_reg) &
+ WCD934X_AMIC_PWR_LVL_MASK) >>
+ WCD934X_AMIC_PWR_LVL_SHIFT) {
+ case WCD934X_AMIC_PWR_LEVEL_LP:
+ snd_soc_component_update_bits(comp, dec_cfg_reg,
+ WCD934X_DEC_PWR_LVL_MASK,
+ WCD934X_DEC_PWR_LVL_LP);
+ break;
+ case WCD934X_AMIC_PWR_LEVEL_HP:
+ snd_soc_component_update_bits(comp, dec_cfg_reg,
+ WCD934X_DEC_PWR_LVL_MASK,
+ WCD934X_DEC_PWR_LVL_HP);
+ break;
+ case WCD934X_AMIC_PWR_LEVEL_DEFAULT:
+ case WCD934X_AMIC_PWR_LEVEL_HYBRID:
+ default:
+ snd_soc_component_update_bits(comp, dec_cfg_reg,
+ WCD934X_DEC_PWR_LVL_MASK,
+ WCD934X_DEC_PWR_LVL_DF);
+ break;
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ hpf_coff_freq = (snd_soc_component_read32(comp, dec_cfg_reg) &
+ TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
+ if (hpf_coff_freq != CF_MIN_3DB_150HZ) {
+ snd_soc_component_update_bits(comp, dec_cfg_reg,
+ TX_HPF_CUT_OFF_FREQ_MASK,
+ CF_MIN_3DB_150HZ << 5);
+ snd_soc_component_update_bits(comp, hpf_gate_reg,
+ WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ_MASK,
+ WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ);
+ /*
+ * Minimum 1 clk cycle delay is required as per
+ * HW spec.
+ */
+ usleep_range(1000, 1010);
+ snd_soc_component_update_bits(comp, hpf_gate_reg,
+ WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ_MASK,
+ 0);
+ }
+ /* apply gain after decimator is enabled */
+ snd_soc_component_write(comp, tx_gain_ctl_reg,
+ snd_soc_component_read32(comp,
+ tx_gain_ctl_reg));
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ hpf_coff_freq = (snd_soc_component_read32(comp, dec_cfg_reg) &
+ TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
+
+ if (hpf_coff_freq != CF_MIN_3DB_150HZ) {
+ snd_soc_component_update_bits(comp, dec_cfg_reg,
+ TX_HPF_CUT_OFF_FREQ_MASK,
+ hpf_coff_freq << 5);
+ snd_soc_component_update_bits(comp, hpf_gate_reg,
+ WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ_MASK,
+ WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ);
+ /*
+ * Minimum 1 clk cycle delay is required as per
+ * HW spec.
+ */
+ usleep_range(1000, 1010);
+ snd_soc_component_update_bits(comp, hpf_gate_reg,
+ WCD934X_HPH_CUTOFF_FREQ_CHANGE_REQ_MASK,
+ 0);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_component_update_bits(comp, tx_vol_ctl_reg,
+ 0x10, 0x00);
+ snd_soc_component_update_bits(comp, dec_cfg_reg,
+ WCD934X_DEC_PWR_LVL_MASK,
+ WCD934X_DEC_PWR_LVL_DF);
+ break;
+ };
+out:
+ kfree(wname);
+ return ret;
+}
+
+static void wcd934x_codec_set_tx_hold(struct snd_soc_component *comp,
+ u16 amic_reg, bool set)
+{
+ u8 mask = 0x20;
+ u8 val;
+
+ if (amic_reg == WCD934X_ANA_AMIC1 ||
+ amic_reg == WCD934X_ANA_AMIC3)
+ mask = 0x40;
+
+ val = set ? mask : 0x00;
+
+ switch (amic_reg) {
+ case WCD934X_ANA_AMIC1:
+ case WCD934X_ANA_AMIC2:
+ snd_soc_component_update_bits(comp, WCD934X_ANA_AMIC2,
+ mask, val);
+ break;
+ case WCD934X_ANA_AMIC3:
+ case WCD934X_ANA_AMIC4:
+ snd_soc_component_update_bits(comp, WCD934X_ANA_AMIC4,
+ mask, val);
+ break;
+ default:
+ break;
+ }
+}
+
+static int wcd934x_codec_enable_adc(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ wcd934x_codec_set_tx_hold(comp, w->reg, true);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
static const struct snd_soc_dapm_widget wcd934x_dapm_widgets[] = {
/* Analog Outputs */
SND_SOC_DAPM_OUTPUT("EAR"),
@@ -3529,6 +4508,174 @@ static const struct snd_soc_dapm_widget wcd934x_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
wcd934x_codec_enable_mclk,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* TX */
+ SND_SOC_DAPM_INPUT("AMIC1"),
+ SND_SOC_DAPM_INPUT("AMIC2"),
+ SND_SOC_DAPM_INPUT("AMIC3"),
+ SND_SOC_DAPM_INPUT("AMIC4"),
+ SND_SOC_DAPM_INPUT("AMIC5"),
+ SND_SOC_DAPM_INPUT("DMIC0 Pin"),
+ SND_SOC_DAPM_INPUT("DMIC1 Pin"),
+ SND_SOC_DAPM_INPUT("DMIC2 Pin"),
+ SND_SOC_DAPM_INPUT("DMIC3 Pin"),
+ SND_SOC_DAPM_INPUT("DMIC4 Pin"),
+ SND_SOC_DAPM_INPUT("DMIC5 Pin"),
+
+ SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
+ AIF1_CAP, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_OUT_E("AIF2 CAP", "AIF2 Capture", 0, SND_SOC_NOPM,
+ AIF2_CAP, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_OUT_E("AIF3 CAP", "AIF3 Capture", 0, SND_SOC_NOPM,
+ AIF3_CAP, 0, wcd934x_codec_enable_slim,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER("SLIM TX0", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX2", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX3", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX4", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX5", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX6", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX7", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX8", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX9", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX10", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX11", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SLIM TX13", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* Digital Mic Inputs */
+ SND_SOC_DAPM_ADC_E("DMIC0", NULL, SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_dmic,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_dmic,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_dmic,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_dmic,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_dmic,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+ wcd934x_codec_enable_dmic,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX("DMIC MUX0", SND_SOC_NOPM, 0, 0, &tx_dmic_mux0),
+ SND_SOC_DAPM_MUX("DMIC MUX1", SND_SOC_NOPM, 0, 0, &tx_dmic_mux1),
+ SND_SOC_DAPM_MUX("DMIC MUX2", SND_SOC_NOPM, 0, 0, &tx_dmic_mux2),
+ SND_SOC_DAPM_MUX("DMIC MUX3", SND_SOC_NOPM, 0, 0, &tx_dmic_mux3),
+ SND_SOC_DAPM_MUX("DMIC MUX4", SND_SOC_NOPM, 0, 0, &tx_dmic_mux4),
+ SND_SOC_DAPM_MUX("DMIC MUX5", SND_SOC_NOPM, 0, 0, &tx_dmic_mux5),
+ SND_SOC_DAPM_MUX("DMIC MUX6", SND_SOC_NOPM, 0, 0, &tx_dmic_mux6),
+ SND_SOC_DAPM_MUX("DMIC MUX7", SND_SOC_NOPM, 0, 0, &tx_dmic_mux7),
+ SND_SOC_DAPM_MUX("DMIC MUX8", SND_SOC_NOPM, 0, 0, &tx_dmic_mux8),
+ SND_SOC_DAPM_MUX("AMIC MUX0", SND_SOC_NOPM, 0, 0, &tx_amic_mux0),
+ SND_SOC_DAPM_MUX("AMIC MUX1", SND_SOC_NOPM, 0, 0, &tx_amic_mux1),
+ SND_SOC_DAPM_MUX("AMIC MUX2", SND_SOC_NOPM, 0, 0, &tx_amic_mux2),
+ SND_SOC_DAPM_MUX("AMIC MUX3", SND_SOC_NOPM, 0, 0, &tx_amic_mux3),
+ SND_SOC_DAPM_MUX("AMIC MUX4", SND_SOC_NOPM, 0, 0, &tx_amic_mux4),
+ SND_SOC_DAPM_MUX("AMIC MUX5", SND_SOC_NOPM, 0, 0, &tx_amic_mux5),
+ SND_SOC_DAPM_MUX("AMIC MUX6", SND_SOC_NOPM, 0, 0, &tx_amic_mux6),
+ SND_SOC_DAPM_MUX("AMIC MUX7", SND_SOC_NOPM, 0, 0, &tx_amic_mux7),
+ SND_SOC_DAPM_MUX("AMIC MUX8", SND_SOC_NOPM, 0, 0, &tx_amic_mux8),
+ SND_SOC_DAPM_MUX_E("ADC MUX0", WCD934X_CDC_TX0_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux0_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX1", WCD934X_CDC_TX1_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux1_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX2", WCD934X_CDC_TX2_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux2_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX3", WCD934X_CDC_TX3_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux3_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX4", WCD934X_CDC_TX4_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux4_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX5", WCD934X_CDC_TX5_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux5_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX6", WCD934X_CDC_TX6_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux6_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX7", WCD934X_CDC_TX7_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux7_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("ADC MUX8", WCD934X_CDC_TX8_TX_PATH_CTL, 5, 0,
+ &tx_adc_mux8_mux, wcd934x_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC1", NULL, WCD934X_ANA_AMIC1, 7, 0,
+ wcd934x_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_ADC_E("ADC2", NULL, WCD934X_ANA_AMIC2, 7, 0,
+ wcd934x_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_ADC_E("ADC3", NULL, WCD934X_ANA_AMIC3, 7, 0,
+ wcd934x_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_ADC_E("ADC4", NULL, WCD934X_ANA_AMIC4, 7, 0,
+ wcd934x_codec_enable_adc, SND_SOC_DAPM_PRE_PMU),
+ SND_SOC_DAPM_SUPPLY("MIC BIAS1", WCD934X_ANA_MICB1, 6, 0, NULL,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("MIC BIAS2", WCD934X_ANA_MICB2, 6, 0, NULL,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("MIC BIAS3", WCD934X_ANA_MICB3, 6, 0, NULL,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("MIC BIAS4", WCD934X_ANA_MICB4, 6, 0, NULL,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("AMIC4_5 SEL", SND_SOC_NOPM, 0, 0, &tx_amic4_5),
+ SND_SOC_DAPM_MUX("CDC_IF TX0 MUX", SND_SOC_NOPM, WCD934X_TX0, 0,
+ &cdc_if_tx0_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX1 MUX", SND_SOC_NOPM, WCD934X_TX1, 0,
+ &cdc_if_tx1_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX2 MUX", SND_SOC_NOPM, WCD934X_TX2, 0,
+ &cdc_if_tx2_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX3 MUX", SND_SOC_NOPM, WCD934X_TX3, 0,
+ &cdc_if_tx3_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX4 MUX", SND_SOC_NOPM, WCD934X_TX4, 0,
+ &cdc_if_tx4_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX5 MUX", SND_SOC_NOPM, WCD934X_TX5, 0,
+ &cdc_if_tx5_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX6 MUX", SND_SOC_NOPM, WCD934X_TX6, 0,
+ &cdc_if_tx6_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX7 MUX", SND_SOC_NOPM, WCD934X_TX7, 0,
+ &cdc_if_tx7_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX8 MUX", SND_SOC_NOPM, WCD934X_TX8, 0,
+ &cdc_if_tx8_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX9 MUX", SND_SOC_NOPM, WCD934X_TX9, 0,
+ &cdc_if_tx9_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX10 MUX", SND_SOC_NOPM, WCD934X_TX10, 0,
+ &cdc_if_tx10_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX11 MUX", SND_SOC_NOPM, WCD934X_TX11, 0,
+ &cdc_if_tx11_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX11 INP1 MUX", SND_SOC_NOPM, WCD934X_TX11, 0,
+ &cdc_if_tx11_inp1_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX13 MUX", SND_SOC_NOPM, WCD934X_TX13, 0,
+ &cdc_if_tx13_mux),
+ SND_SOC_DAPM_MUX("CDC_IF TX13 INP1 MUX", SND_SOC_NOPM, WCD934X_TX13, 0,
+ &cdc_if_tx13_inp1_mux),
+ SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
+ aif1_slim_cap_mixer,
+ ARRAY_SIZE(aif1_slim_cap_mixer)),
+ SND_SOC_DAPM_MIXER("AIF2_CAP Mixer", SND_SOC_NOPM, AIF2_CAP, 0,
+ aif2_slim_cap_mixer,
+ ARRAY_SIZE(aif2_slim_cap_mixer)),
+ SND_SOC_DAPM_MIXER("AIF3_CAP Mixer", SND_SOC_NOPM, AIF3_CAP, 0,
+ aif3_slim_cap_mixer,
+ ARRAY_SIZE(aif3_slim_cap_mixer)),
};
static const struct snd_soc_component_driver wcd934x_component_drv = {
--
2.20.1
1
0
25 Dec '19
The patch
ASoC: wcd934x: add audio routings
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From da3e83f8bb866a91945ef5c47bdb25de189a381e Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Date: Thu, 19 Dec 2019 10:31:49 +0000
Subject: [PATCH] ASoC: wcd934x: add audio routings
This patch adds audio routing for both playback and capture.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Link: https://lore.kernel.org/r/20191219103153.14875-8-srinivas.kandagatla@linaro…
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart(a)linux.intel.com>
Signed-off-by: Mark Brown <broonie(a)kernel.org>
---
sound/soc/codecs/wcd934x.c | 290 +++++++++++++++++++++++++++++++++++++
1 file changed, 290 insertions(+)
diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c
index 24f78a0b7f5a..158e878abd6c 100644
--- a/sound/soc/codecs/wcd934x.c
+++ b/sound/soc/codecs/wcd934x.c
@@ -135,6 +135,162 @@
} \
}
+#define WCD934X_INTERPOLATOR_PATH(id) \
+ {"RX INT" #id "_1 MIX1 INP0", "RX0", "SLIM RX0"}, \
+ {"RX INT" #id "_1 MIX1 INP0", "RX1", "SLIM RX1"}, \
+ {"RX INT" #id "_1 MIX1 INP0", "RX2", "SLIM RX2"}, \
+ {"RX INT" #id "_1 MIX1 INP0", "RX3", "SLIM RX3"}, \
+ {"RX INT" #id "_1 MIX1 INP0", "RX4", "SLIM RX4"}, \
+ {"RX INT" #id "_1 MIX1 INP0", "RX5", "SLIM RX5"}, \
+ {"RX INT" #id "_1 MIX1 INP0", "RX6", "SLIM RX6"}, \
+ {"RX INT" #id "_1 MIX1 INP0", "RX7", "SLIM RX7"}, \
+ {"RX INT" #id "_1 MIX1 INP0", "IIR0", "IIR0"}, \
+ {"RX INT" #id "_1 MIX1 INP0", "IIR1", "IIR1"}, \
+ {"RX INT" #id "_1 MIX1 INP1", "RX0", "SLIM RX0"}, \
+ {"RX INT" #id "_1 MIX1 INP1", "RX1", "SLIM RX1"}, \
+ {"RX INT" #id "_1 MIX1 INP1", "RX2", "SLIM RX2"}, \
+ {"RX INT" #id "_1 MIX1 INP1", "RX3", "SLIM RX3"}, \
+ {"RX INT" #id "_1 MIX1 INP1", "RX4", "SLIM RX4"}, \
+ {"RX INT" #id "_1 MIX1 INP1", "RX5", "SLIM RX5"}, \
+ {"RX INT" #id "_1 MIX1 INP1", "RX6", "SLIM RX6"}, \
+ {"RX INT" #id "_1 MIX1 INP1", "RX7", "SLIM RX7"}, \
+ {"RX INT" #id "_1 MIX1 INP1", "IIR0", "IIR0"}, \
+ {"RX INT" #id "_1 MIX1 INP1", "IIR1", "IIR1"}, \
+ {"RX INT" #id "_1 MIX1 INP2", "RX0", "SLIM RX0"}, \
+ {"RX INT" #id "_1 MIX1 INP2", "RX1", "SLIM RX1"}, \
+ {"RX INT" #id "_1 MIX1 INP2", "RX2", "SLIM RX2"}, \
+ {"RX INT" #id "_1 MIX1 INP2", "RX3", "SLIM RX3"}, \
+ {"RX INT" #id "_1 MIX1 INP2", "RX4", "SLIM RX4"}, \
+ {"RX INT" #id "_1 MIX1 INP2", "RX5", "SLIM RX5"}, \
+ {"RX INT" #id "_1 MIX1 INP2", "RX6", "SLIM RX6"}, \
+ {"RX INT" #id "_1 MIX1 INP2", "RX7", "SLIM RX7"}, \
+ {"RX INT" #id "_1 MIX1 INP2", "IIR0", "IIR0"}, \
+ {"RX INT" #id "_1 MIX1 INP2", "IIR1", "IIR1"}, \
+ {"RX INT" #id "_1 MIX1", NULL, "RX INT" #id "_1 MIX1 INP0"}, \
+ {"RX INT" #id "_1 MIX1", NULL, "RX INT" #id "_1 MIX1 INP1"}, \
+ {"RX INT" #id "_1 MIX1", NULL, "RX INT" #id "_1 MIX1 INP2"}, \
+ {"RX INT" #id "_2 MUX", "RX0", "SLIM RX0"}, \
+ {"RX INT" #id "_2 MUX", "RX1", "SLIM RX1"}, \
+ {"RX INT" #id "_2 MUX", "RX2", "SLIM RX2"}, \
+ {"RX INT" #id "_2 MUX", "RX3", "SLIM RX3"}, \
+ {"RX INT" #id "_2 MUX", "RX4", "SLIM RX4"}, \
+ {"RX INT" #id "_2 MUX", "RX5", "SLIM RX5"}, \
+ {"RX INT" #id "_2 MUX", "RX6", "SLIM RX6"}, \
+ {"RX INT" #id "_2 MUX", "RX7", "SLIM RX7"}, \
+ {"RX INT" #id "_2 MUX", NULL, "INT" #id "_CLK"}, \
+ {"RX INT" #id "_2 MUX", NULL, "DSMDEM" #id "_CLK"}, \
+ {"RX INT" #id "_2 INTERP", NULL, "RX INT" #id "_2 MUX"}, \
+ {"RX INT" #id " SEC MIX", NULL, "RX INT" #id "_2 INTERP"}, \
+ {"RX INT" #id "_1 INTERP", NULL, "RX INT" #id "_1 MIX1"}, \
+ {"RX INT" #id "_1 INTERP", NULL, "INT" #id "_CLK"}, \
+ {"RX INT" #id "_1 INTERP", NULL, "DSMDEM" #id "_CLK"}, \
+ {"RX INT" #id " SEC MIX", NULL, "RX INT" #id "_1 INTERP"}
+
+#define WCD934X_INTERPOLATOR_MIX2(id) \
+ {"RX INT" #id " MIX2", NULL, "RX INT" #id " SEC MIX"}, \
+ {"RX INT" #id " MIX2", NULL, "RX INT" #id " MIX2 INP"}
+
+#define WCD934X_SLIM_RX_AIF_PATH(id) \
+ {"SLIM RX"#id" MUX", "AIF1_PB", "AIF1 PB"}, \
+ {"SLIM RX"#id" MUX", "AIF2_PB", "AIF2 PB"}, \
+ {"SLIM RX"#id" MUX", "AIF3_PB", "AIF3 PB"}, \
+ {"SLIM RX"#id" MUX", "AIF4_PB", "AIF4 PB"}, \
+ {"SLIM RX"#id, NULL, "SLIM RX"#id" MUX"}
+
+#define WCD934X_ADC_MUX(id) \
+ {"ADC MUX" #id, "DMIC", "DMIC MUX" #id }, \
+ {"ADC MUX" #id, "AMIC", "AMIC MUX" #id }, \
+ {"DMIC MUX" #id, "DMIC0", "DMIC0"}, \
+ {"DMIC MUX" #id, "DMIC1", "DMIC1"}, \
+ {"DMIC MUX" #id, "DMIC2", "DMIC2"}, \
+ {"DMIC MUX" #id, "DMIC3", "DMIC3"}, \
+ {"DMIC MUX" #id, "DMIC4", "DMIC4"}, \
+ {"DMIC MUX" #id, "DMIC5", "DMIC5"}, \
+ {"AMIC MUX" #id, "ADC1", "ADC1"}, \
+ {"AMIC MUX" #id, "ADC2", "ADC2"}, \
+ {"AMIC MUX" #id, "ADC3", "ADC3"}, \
+ {"AMIC MUX" #id, "ADC4", "ADC4"}
+
+#define WCD934X_IIR_INP_MUX(id) \
+ {"IIR" #id, NULL, "IIR" #id " INP0 MUX"}, \
+ {"IIR" #id " INP0 MUX", "DEC0", "ADC MUX0"}, \
+ {"IIR" #id " INP0 MUX", "DEC1", "ADC MUX1"}, \
+ {"IIR" #id " INP0 MUX", "DEC2", "ADC MUX2"}, \
+ {"IIR" #id " INP0 MUX", "DEC3", "ADC MUX3"}, \
+ {"IIR" #id " INP0 MUX", "DEC4", "ADC MUX4"}, \
+ {"IIR" #id " INP0 MUX", "DEC5", "ADC MUX5"}, \
+ {"IIR" #id " INP0 MUX", "DEC6", "ADC MUX6"}, \
+ {"IIR" #id " INP0 MUX", "DEC7", "ADC MUX7"}, \
+ {"IIR" #id " INP0 MUX", "DEC8", "ADC MUX8"}, \
+ {"IIR" #id " INP0 MUX", "RX0", "SLIM RX0"}, \
+ {"IIR" #id " INP0 MUX", "RX1", "SLIM RX1"}, \
+ {"IIR" #id " INP0 MUX", "RX2", "SLIM RX2"}, \
+ {"IIR" #id " INP0 MUX", "RX3", "SLIM RX3"}, \
+ {"IIR" #id " INP0 MUX", "RX4", "SLIM RX4"}, \
+ {"IIR" #id " INP0 MUX", "RX5", "SLIM RX5"}, \
+ {"IIR" #id " INP0 MUX", "RX6", "SLIM RX6"}, \
+ {"IIR" #id " INP0 MUX", "RX7", "SLIM RX7"}, \
+ {"IIR" #id, NULL, "IIR" #id " INP1 MUX"}, \
+ {"IIR" #id " INP1 MUX", "DEC0", "ADC MUX0"}, \
+ {"IIR" #id " INP1 MUX", "DEC1", "ADC MUX1"}, \
+ {"IIR" #id " INP1 MUX", "DEC2", "ADC MUX2"}, \
+ {"IIR" #id " INP1 MUX", "DEC3", "ADC MUX3"}, \
+ {"IIR" #id " INP1 MUX", "DEC4", "ADC MUX4"}, \
+ {"IIR" #id " INP1 MUX", "DEC5", "ADC MUX5"}, \
+ {"IIR" #id " INP1 MUX", "DEC6", "ADC MUX6"}, \
+ {"IIR" #id " INP1 MUX", "DEC7", "ADC MUX7"}, \
+ {"IIR" #id " INP1 MUX", "DEC8", "ADC MUX8"}, \
+ {"IIR" #id " INP1 MUX", "RX0", "SLIM RX0"}, \
+ {"IIR" #id " INP1 MUX", "RX1", "SLIM RX1"}, \
+ {"IIR" #id " INP1 MUX", "RX2", "SLIM RX2"}, \
+ {"IIR" #id " INP1 MUX", "RX3", "SLIM RX3"}, \
+ {"IIR" #id " INP1 MUX", "RX4", "SLIM RX4"}, \
+ {"IIR" #id " INP1 MUX", "RX5", "SLIM RX5"}, \
+ {"IIR" #id " INP1 MUX", "RX6", "SLIM RX6"}, \
+ {"IIR" #id " INP1 MUX", "RX7", "SLIM RX7"}, \
+ {"IIR" #id, NULL, "IIR" #id " INP2 MUX"}, \
+ {"IIR" #id " INP2 MUX", "DEC0", "ADC MUX0"}, \
+ {"IIR" #id " INP2 MUX", "DEC1", "ADC MUX1"}, \
+ {"IIR" #id " INP2 MUX", "DEC2", "ADC MUX2"}, \
+ {"IIR" #id " INP2 MUX", "DEC3", "ADC MUX3"}, \
+ {"IIR" #id " INP2 MUX", "DEC4", "ADC MUX4"}, \
+ {"IIR" #id " INP2 MUX", "DEC5", "ADC MUX5"}, \
+ {"IIR" #id " INP2 MUX", "DEC6", "ADC MUX6"}, \
+ {"IIR" #id " INP2 MUX", "DEC7", "ADC MUX7"}, \
+ {"IIR" #id " INP2 MUX", "DEC8", "ADC MUX8"}, \
+ {"IIR" #id " INP2 MUX", "RX0", "SLIM RX0"}, \
+ {"IIR" #id " INP2 MUX", "RX1", "SLIM RX1"}, \
+ {"IIR" #id " INP2 MUX", "RX2", "SLIM RX2"}, \
+ {"IIR" #id " INP2 MUX", "RX3", "SLIM RX3"}, \
+ {"IIR" #id " INP2 MUX", "RX4", "SLIM RX4"}, \
+ {"IIR" #id " INP2 MUX", "RX5", "SLIM RX5"}, \
+ {"IIR" #id " INP2 MUX", "RX6", "SLIM RX6"}, \
+ {"IIR" #id " INP2 MUX", "RX7", "SLIM RX7"}, \
+ {"IIR" #id, NULL, "IIR" #id " INP3 MUX"}, \
+ {"IIR" #id " INP3 MUX", "DEC0", "ADC MUX0"}, \
+ {"IIR" #id " INP3 MUX", "DEC1", "ADC MUX1"}, \
+ {"IIR" #id " INP3 MUX", "DEC2", "ADC MUX2"}, \
+ {"IIR" #id " INP3 MUX", "DEC3", "ADC MUX3"}, \
+ {"IIR" #id " INP3 MUX", "DEC4", "ADC MUX4"}, \
+ {"IIR" #id " INP3 MUX", "DEC5", "ADC MUX5"}, \
+ {"IIR" #id " INP3 MUX", "DEC6", "ADC MUX6"}, \
+ {"IIR" #id " INP3 MUX", "DEC7", "ADC MUX7"}, \
+ {"IIR" #id " INP3 MUX", "DEC8", "ADC MUX8"}, \
+ {"IIR" #id " INP3 MUX", "RX0", "SLIM RX0"}, \
+ {"IIR" #id " INP3 MUX", "RX1", "SLIM RX1"}, \
+ {"IIR" #id " INP3 MUX", "RX2", "SLIM RX2"}, \
+ {"IIR" #id " INP3 MUX", "RX3", "SLIM RX3"}, \
+ {"IIR" #id " INP3 MUX", "RX4", "SLIM RX4"}, \
+ {"IIR" #id " INP3 MUX", "RX5", "SLIM RX5"}, \
+ {"IIR" #id " INP3 MUX", "RX6", "SLIM RX6"}, \
+ {"IIR" #id " INP3 MUX", "RX7", "SLIM RX7"}
+
+#define WCD934X_SLIM_TX_AIF_PATH(id) \
+ {"AIF1_CAP Mixer", "SLIM TX" #id, "SLIM TX" #id }, \
+ {"AIF2_CAP Mixer", "SLIM TX" #id, "SLIM TX" #id }, \
+ {"AIF3_CAP Mixer", "SLIM TX" #id, "SLIM TX" #id }, \
+ {"SLIM TX" #id, NULL, "CDC_IF TX" #id " MUX"}
+
enum {
MIC_BIAS_1 = 1,
MIC_BIAS_2,
@@ -4678,6 +4834,138 @@ static const struct snd_soc_dapm_widget wcd934x_dapm_widgets[] = {
ARRAY_SIZE(aif3_slim_cap_mixer)),
};
+static const struct snd_soc_dapm_route wcd934x_audio_map[] = {
+ /* RX0-RX7 */
+ WCD934X_SLIM_RX_AIF_PATH(0),
+ WCD934X_SLIM_RX_AIF_PATH(1),
+ WCD934X_SLIM_RX_AIF_PATH(2),
+ WCD934X_SLIM_RX_AIF_PATH(3),
+ WCD934X_SLIM_RX_AIF_PATH(4),
+ WCD934X_SLIM_RX_AIF_PATH(5),
+ WCD934X_SLIM_RX_AIF_PATH(6),
+ WCD934X_SLIM_RX_AIF_PATH(7),
+
+ /* RX0 Ear out */
+ WCD934X_INTERPOLATOR_PATH(0),
+ WCD934X_INTERPOLATOR_MIX2(0),
+ {"RX INT0 DEM MUX", "CLSH_DSM_OUT", "RX INT0 MIX2"},
+ {"RX INT0 DAC", NULL, "RX INT0 DEM MUX"},
+ {"RX INT0 DAC", NULL, "RX_BIAS"},
+ {"EAR PA", NULL, "RX INT0 DAC"},
+ {"EAR", NULL, "EAR PA"},
+
+ /* RX1 Headphone left */
+ WCD934X_INTERPOLATOR_PATH(1),
+ WCD934X_INTERPOLATOR_MIX2(1),
+ {"RX INT1 MIX3", NULL, "RX INT1 MIX2"},
+ {"RX INT1 DEM MUX", "CLSH_DSM_OUT", "RX INT1 MIX3"},
+ {"RX INT1 DAC", NULL, "RX INT1 DEM MUX"},
+ {"RX INT1 DAC", NULL, "RX_BIAS"},
+ {"HPHL PA", NULL, "RX INT1 DAC"},
+ {"HPHL", NULL, "HPHL PA"},
+
+ /* RX2 Headphone right */
+ WCD934X_INTERPOLATOR_PATH(2),
+ WCD934X_INTERPOLATOR_MIX2(2),
+ {"RX INT2 MIX3", NULL, "RX INT2 MIX2"},
+ {"RX INT2 DEM MUX", "CLSH_DSM_OUT", "RX INT2 MIX3"},
+ {"RX INT2 DAC", NULL, "RX INT2 DEM MUX"},
+ {"RX INT2 DAC", NULL, "RX_BIAS"},
+ {"HPHR PA", NULL, "RX INT2 DAC"},
+ {"HPHR", NULL, "HPHR PA"},
+
+ /* RX3 HIFi LineOut1 */
+ WCD934X_INTERPOLATOR_PATH(3),
+ WCD934X_INTERPOLATOR_MIX2(3),
+ {"RX INT3 MIX3", NULL, "RX INT3 MIX2"},
+ {"RX INT3 DAC", NULL, "RX INT3 MIX3"},
+ {"RX INT3 DAC", NULL, "RX_BIAS"},
+ {"LINEOUT1 PA", NULL, "RX INT3 DAC"},
+ {"LINEOUT1", NULL, "LINEOUT1 PA"},
+
+ /* RX4 HIFi LineOut2 */
+ WCD934X_INTERPOLATOR_PATH(4),
+ WCD934X_INTERPOLATOR_MIX2(4),
+ {"RX INT4 MIX3", NULL, "RX INT4 MIX2"},
+ {"RX INT4 DAC", NULL, "RX INT4 MIX3"},
+ {"RX INT4 DAC", NULL, "RX_BIAS"},
+ {"LINEOUT2 PA", NULL, "RX INT4 DAC"},
+ {"LINEOUT2", NULL, "LINEOUT2 PA"},
+
+ /* RX7 Speaker Left Out PA */
+ WCD934X_INTERPOLATOR_PATH(7),
+ WCD934X_INTERPOLATOR_MIX2(7),
+ {"RX INT7 CHAIN", NULL, "RX INT7 MIX2"},
+ {"RX INT7 CHAIN", NULL, "RX_BIAS"},
+ {"RX INT7 CHAIN", NULL, "SBOOST0"},
+ {"RX INT7 CHAIN", NULL, "SBOOST0_CLK"},
+ {"SPK1 OUT", NULL, "RX INT7 CHAIN"},
+
+ /* RX8 Speaker Right Out PA */
+ WCD934X_INTERPOLATOR_PATH(8),
+ {"RX INT8 CHAIN", NULL, "RX INT8 SEC MIX"},
+ {"RX INT8 CHAIN", NULL, "RX_BIAS"},
+ {"RX INT8 CHAIN", NULL, "SBOOST1"},
+ {"RX INT8 CHAIN", NULL, "SBOOST1_CLK"},
+ {"SPK2 OUT", NULL, "RX INT8 CHAIN"},
+
+ /* Tx */
+ {"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
+ {"AIF2 CAP", NULL, "AIF2_CAP Mixer"},
+ {"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
+
+ WCD934X_SLIM_TX_AIF_PATH(0),
+ WCD934X_SLIM_TX_AIF_PATH(1),
+ WCD934X_SLIM_TX_AIF_PATH(2),
+ WCD934X_SLIM_TX_AIF_PATH(3),
+ WCD934X_SLIM_TX_AIF_PATH(4),
+ WCD934X_SLIM_TX_AIF_PATH(5),
+ WCD934X_SLIM_TX_AIF_PATH(6),
+ WCD934X_SLIM_TX_AIF_PATH(7),
+ WCD934X_SLIM_TX_AIF_PATH(8),
+
+ WCD934X_ADC_MUX(0),
+ WCD934X_ADC_MUX(1),
+ WCD934X_ADC_MUX(2),
+ WCD934X_ADC_MUX(3),
+ WCD934X_ADC_MUX(4),
+ WCD934X_ADC_MUX(5),
+ WCD934X_ADC_MUX(6),
+ WCD934X_ADC_MUX(7),
+ WCD934X_ADC_MUX(8),
+
+ {"CDC_IF TX0 MUX", "DEC0", "ADC MUX0"},
+ {"CDC_IF TX1 MUX", "DEC1", "ADC MUX1"},
+ {"CDC_IF TX2 MUX", "DEC2", "ADC MUX2"},
+ {"CDC_IF TX3 MUX", "DEC3", "ADC MUX3"},
+ {"CDC_IF TX4 MUX", "DEC4", "ADC MUX4"},
+ {"CDC_IF TX5 MUX", "DEC5", "ADC MUX5"},
+ {"CDC_IF TX6 MUX", "DEC6", "ADC MUX6"},
+ {"CDC_IF TX7 MUX", "DEC7", "ADC MUX7"},
+ {"CDC_IF TX8 MUX", "DEC8", "ADC MUX8"},
+
+ {"AMIC4_5 SEL", "AMIC4", "AMIC4"},
+ {"AMIC4_5 SEL", "AMIC5", "AMIC5"},
+
+ { "DMIC0", NULL, "DMIC0 Pin" },
+ { "DMIC1", NULL, "DMIC1 Pin" },
+ { "DMIC2", NULL, "DMIC2 Pin" },
+ { "DMIC3", NULL, "DMIC3 Pin" },
+ { "DMIC4", NULL, "DMIC4 Pin" },
+ { "DMIC5", NULL, "DMIC5 Pin" },
+
+ {"ADC1", NULL, "AMIC1"},
+ {"ADC2", NULL, "AMIC2"},
+ {"ADC3", NULL, "AMIC3"},
+ {"ADC4", NULL, "AMIC4_5 SEL"},
+
+ WCD934X_IIR_INP_MUX(0),
+ WCD934X_IIR_INP_MUX(1),
+
+ {"SRC0", NULL, "IIR0"},
+ {"SRC1", NULL, "IIR1"},
+};
+
static const struct snd_soc_component_driver wcd934x_component_drv = {
.probe = wcd934x_comp_probe,
.remove = wcd934x_comp_remove,
@@ -4686,6 +4974,8 @@ static const struct snd_soc_component_driver wcd934x_component_drv = {
.num_controls = ARRAY_SIZE(wcd934x_snd_controls),
.dapm_widgets = wcd934x_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(wcd934x_dapm_widgets),
+ .dapm_routes = wcd934x_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(wcd934x_audio_map),
};
static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd)
--
2.20.1
1
0
[alsa-devel] Applied "ASoC: qcom: dt-bindings: Add compatible for DB845c and Lenovo Yoga" to the asoc tree
by Mark Brown 25 Dec '19
by Mark Brown 25 Dec '19
25 Dec '19
The patch
ASoC: qcom: dt-bindings: Add compatible for DB845c and Lenovo Yoga
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From 834d899794f4ec3bbf9836c85e8f76b7de6e8a59 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Date: Thu, 19 Dec 2019 10:31:52 +0000
Subject: [PATCH] ASoC: qcom: dt-bindings: Add compatible for DB845c and Lenovo
Yoga
This patch adds compatible strings for DB845c and Lenovo Yoga C630
soundcard. Based on this compatible strings common machine driver
will be in better position to setup board specific configuration.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Acked-by: Rob Herring <robh(a)kernel.org>
Link: https://lore.kernel.org/r/20191219103153.14875-11-srinivas.kandagatla@linar…
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart(a)linux.intel.com>
Signed-off-by: Mark Brown <broonie(a)kernel.org>
---
Documentation/devicetree/bindings/sound/qcom,sdm845.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/sound/qcom,sdm845.txt b/Documentation/devicetree/bindings/sound/qcom,sdm845.txt
index 408c4837e6d5..ca8c89e88bfa 100644
--- a/Documentation/devicetree/bindings/sound/qcom,sdm845.txt
+++ b/Documentation/devicetree/bindings/sound/qcom,sdm845.txt
@@ -5,7 +5,10 @@ This binding describes the SDM845 sound card, which uses qdsp for audio.
- compatible:
Usage: required
Value type: <stringlist>
- Definition: must be "qcom,sdm845-sndcard"
+ Definition: must be one of this
+ "qcom,sdm845-sndcard"
+ "qcom,db845c-sndcard"
+ "lenovo,yoga-c630-sndcard"
- audio-routing:
Usage: Optional
--
2.20.1
1
0
[alsa-devel] Applied "ASoC: qcom: sdm845: add support to DB845c and Lenovo Yoga" to the asoc tree
by Mark Brown 25 Dec '19
by Mark Brown 25 Dec '19
25 Dec '19
The patch
ASoC: qcom: sdm845: add support to DB845c and Lenovo Yoga
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From 5caf64c633a3564f70e734868254281b25932fc0 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Date: Thu, 19 Dec 2019 10:31:53 +0000
Subject: [PATCH] ASoC: qcom: sdm845: add support to DB845c and Lenovo Yoga
This patch adds support to Lenovo Yoga c630 compatible strings
and related setup to the sound machine driver.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla(a)linaro.org>
Link: https://lore.kernel.org/r/20191219103153.14875-12-srinivas.kandagatla@linar…
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart(a)linux.intel.com>
Signed-off-by: Mark Brown <broonie(a)kernel.org>
---
sound/soc/qcom/sdm845.c | 86 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 85 insertions(+), 1 deletion(-)
diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index 28f3cef696e6..3b5547a27aad 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -24,6 +24,9 @@
#define RIGHT_SPK_TDM_TX_MASK 0xC0
#define SPK_TDM_RX_MASK 0x03
#define NUM_TDM_SLOTS 8
+#define SLIM_MAX_TX_PORTS 16
+#define SLIM_MAX_RX_PORTS 16
+#define WCD934X_DEFAULT_MCLK_RATE 9600000
struct sdm845_snd_data {
struct snd_soc_jack jack;
@@ -36,6 +39,39 @@ struct sdm845_snd_data {
static unsigned int tdm_slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28};
+static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+ u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
+ int ret = 0, i;
+
+ for (i = 0 ; i < dai_link->num_codecs; i++) {
+ ret = snd_soc_dai_get_channel_map(rtd->codec_dais[i],
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+
+ if (ret != 0 && ret != -ENOTSUPP) {
+ pr_err("failed to get codec chan map, err:%d\n", ret);
+ return ret;
+ } else if (ret == -ENOTSUPP) {
+ /* Ignore unsupported */
+ continue;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
+ rx_ch_cnt, rx_ch);
+ else
+ ret = snd_soc_dai_set_channel_map(cpu_dai, tx_ch_cnt,
+ tx_ch, 0, NULL);
+ }
+
+ return 0;
+}
+
static int sdm845_tdm_snd_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -151,6 +187,11 @@ static int sdm845_snd_hw_params(struct snd_pcm_substream *substream,
case QUATERNARY_TDM_TX_0:
ret = sdm845_tdm_snd_hw_params(substream, params);
break;
+ case SLIMBUS_0_RX...SLIMBUS_6_TX:
+ ret = sdm845_slim_snd_hw_params(substream, params);
+ break;
+ case QUATERNARY_MI2S_RX:
+ break;
default:
pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
break;
@@ -173,7 +214,20 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(card);
struct snd_jack *jack;
- int rval;
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ /*
+ * Codec SLIMBUS configuration
+ * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
+ * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
+ * TX14, TX15, TX16
+ */
+ unsigned int rx_ch[SLIM_MAX_RX_PORTS] = {144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 156};
+ unsigned int tx_ch[SLIM_MAX_TX_PORTS] = {128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143};
+ int rval, i;
+
if (!pdata->jack_setup) {
rval = snd_soc_card_jack_new(card, "Headset Jack",
@@ -211,6 +265,21 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
return rval;
}
break;
+ case SLIMBUS_0_RX...SLIMBUS_6_TX:
+ for (i = 0 ; i < dai_link->num_codecs; i++) {
+ rval = snd_soc_dai_set_channel_map(rtd->codec_dais[i],
+ ARRAY_SIZE(tx_ch),
+ tx_ch,
+ ARRAY_SIZE(rx_ch),
+ rx_ch);
+ if (rval != 0 && rval != -ENOTSUPP)
+ return rval;
+
+ snd_soc_dai_set_sysclk(rtd->codec_dais[i], 0,
+ WCD934X_DEFAULT_MCLK_RATE,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ }
+ break;
default:
break;
}
@@ -256,6 +325,14 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream)
}
snd_soc_dai_set_fmt(cpu_dai, fmt);
snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
+ break;
+ case QUATERNARY_MI2S_RX:
+ snd_soc_dai_set_sysclk(cpu_dai,
+ Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
+ MI2S_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
+ snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
+
+
break;
case QUATERNARY_TDM_RX_0:
@@ -294,6 +371,8 @@ static int sdm845_snd_startup(struct snd_pcm_substream *substream)
}
}
break;
+ case SLIMBUS_0_RX...SLIMBUS_6_TX:
+ break;
default:
pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
@@ -338,6 +417,9 @@ static void sdm845_snd_shutdown(struct snd_pcm_substream *substream)
0, SNDRV_PCM_STREAM_PLAYBACK);
}
break;
+ case SLIMBUS_0_RX...SLIMBUS_6_TX:
+ case QUATERNARY_MI2S_RX:
+ break;
default:
pr_err("%s: invalid dai id 0x%x\n", __func__, cpu_dai->id);
@@ -451,6 +533,8 @@ static int sdm845_snd_platform_remove(struct platform_device *pdev)
static const struct of_device_id sdm845_snd_device_id[] = {
{ .compatible = "qcom,sdm845-sndcard" },
+ { .compatible = "qcom,db845c-sndcard" },
+ { .compatible = "lenovo,yoga-c630-sndcard" },
{},
};
MODULE_DEVICE_TABLE(of, sdm845_snd_device_id);
--
2.20.1
1
0
25 Dec '19
On Mon, Dec 23, 2019 at 02:10:12AM +0000, jeff_chang(張世佳) wrote:
> --> When I check other driver at sound/soc/codecs/ folder, I just follow what others do.
> It seems in .h --> /* SPDX-Liencese-Identifier: GPL-2.0 */
> In .c --> // SPDK-Liencese-Identifier: GPL-2.0
> Is it correct?
Yes, headers use C style comments and source files use C++ style.
2
2
[alsa-devel] [PATCH 1/1] [PATCH] ALSA: usb-audio: Add support for Presonus Studio 1810c
by mickflemm@gmail.com 25 Dec '19
by mickflemm@gmail.com 25 Dec '19
25 Dec '19
This patch adds support for Presonus Studio 1810c, a usb interface
that's UAC2 compliant with a few quirks and a few extra hw-specific
controls. I've tested all 3 altsettings and the added switch
controls and they work as expected.
More infos on the card:
https://www.presonus.com/products/Studio-1810c
Note that this work is based on packet inspection with
usbmon. I just wanted to get this card to work for using
it on our open-source radio station:
https://github.com/UoC-Radio
Signed-off-by: Nick Kossifidis <mickflemm(a)gmail.com>
---
sound/usb/Makefile | 1 +
sound/usb/format.c | 17 ++
sound/usb/mixer_quirks.c | 5 +
sound/usb/mixer_s1810c.c | 565 +++++++++++++++++++++++++++++++++++++++
sound/usb/mixer_s1810c.h | 6 +
sound/usb/quirks.c | 34 +++
6 files changed, 628 insertions(+)
create mode 100644 sound/usb/mixer_s1810c.c
create mode 100644 sound/usb/mixer_s1810c.h
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 78edd7d2f..56031026b 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -13,6 +13,7 @@ snd-usb-audio-objs := card.o \
mixer_scarlett.o \
mixer_scarlett_gen2.o \
mixer_us16x08.o \
+ mixer_s1810c.o \
pcm.o \
power.o \
proc.o \
diff --git a/sound/usb/format.c b/sound/usb/format.c
index d79db7130..edf3f2a55 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -262,6 +262,23 @@ static int parse_uac2_sample_rate_range(struct snd_usb_audio *chip,
}
for (rate = min; rate <= max; rate += res) {
+
+ /*
+ * Presonus Studio 1810c anounces invalid
+ * sampling rates for its streams.
+ */
+ if (chip->usb_id == USB_ID(0x0194f, 0x010c) &&
+ ((rate > 48000 && fp->altsetting == 1) ||
+ ((rate < 88200 || rate > 96000)
+ && fp->altsetting == 2) ||
+ ((rate < 176400 || rate > 192000)
+ && fp->altsetting == 3))) {
+ if (res)
+ continue;
+ else
+ break;
+ }
+
if (fp->rate_table)
fp->rate_table[nr_rates] = rate;
if (!fp->rate_min || rate < fp->rate_min)
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 39e27ae6c..71e705fab 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -34,6 +34,7 @@
#include "mixer_scarlett.h"
#include "mixer_scarlett_gen2.h"
#include "mixer_us16x08.h"
+#include "mixer_s1810c.h"
#include "helper.h"
struct std_mono_table {
@@ -2277,6 +2278,10 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case USB_ID(0x2a39, 0x3fd4): /* RME */
err = snd_rme_controls_create(mixer);
break;
+
+ case USB_ID(0x0194f, 0x010c): /* Presonus Studio 1810c */
+ err = snd_sc1810_init_mixer(mixer);
+ break;
}
return err;
diff --git a/sound/usb/mixer_s1810c.c b/sound/usb/mixer_s1810c.c
new file mode 100644
index 000000000..ff86e4aab
--- /dev/null
+++ b/sound/usb/mixer_s1810c.c
@@ -0,0 +1,565 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Presonus Studio 1810c driver for ALSA
+ * Copyright (C) 2019 Nick Kossifidis <mickflemm(a)gmail.com>
+ *
+ * Based on reverse engineering of the communication protocol
+ * between the windows driver / Univeral Control (UC) program
+ * and the device, through usbmon.
+ *
+ * For now this bypasses the mixer, with all channels split,
+ * so that the software can mix with greater flexibility.
+ * It also adds controls for the 4 buttons on the front of
+ * the device.
+ */
+#include <linux/usb.h>
+#include <linux/usb/audio-v2.h>
+#include <sound/control.h>
+#include <linux/slab.h>
+
+#include "usbaudio.h"
+#include "mixer.h"
+#include "mixer_quirks.h"
+#include "helper.h"
+
+#define SC1810C_CMD_REQ 160
+#define SC1810C_CMD_REQTYPE \
+ (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT)
+#define SC1810C_CMD_F1 0x50617269
+#define SC1810C_CMD_F2 0x14
+
+/*
+ * DISCLAIMER: These are just guesses based on the
+ * dumps I got.
+ *
+ * It seems like a selects between
+ * device (0), mixer (0x64) and output (0x65)
+ *
+ * For mixer (0x64):
+ * * b selects an input channel (see below).
+ * * c selects an output channel pair (see below).
+ * * d selects left (0) or right (1) of that pair.
+ * * e 0-> disconnect, 0x01000000-> connect,
+ * 0x0109-> used for stereo-linking channels,
+ * e is also used for setting volume levels
+ * in which case b is also set so I guess
+ * this way it is possible to set the volume
+ * level from the specified input to the
+ * specified output.
+ *
+ * IN Channels:
+ * 0 - 7 Mic/Inst/Line (Analog inputs)
+ * 8 - 9 S/PDIF
+ * 10 - 17 ADAT
+ * 18 - 35 DAW (Inputs from the host)
+ *
+ * OUT Channels (pairs):
+ * 0 -> Main out
+ * 1 -> Line1/2
+ * 2 -> Line3/4
+ * 3 -> S/PDIF
+ * 4 -> ADAT?
+ *
+ * For device (0):
+ * * b and c are not used, at least not on the
+ * dumps I got.
+ * * d sets the control id to be modified
+ * (see below).
+ * * e sets the setting for that control.
+ * (so for the switches I was interested
+ * in it's 0/1)
+ *
+ * For output (0x65):
+ * * b is the output channel (see above).
+ * * c is zero.
+ * * e I guess the same as with mixer except 0x0109
+ * which I didn't see in my dumps.
+ *
+ * The two fixed fields have the same values for
+ * mixer and output but a different set for device.
+ */
+struct s1810c_ctl_packet {
+ uint32_t a;
+ uint32_t b;
+ uint32_t fixed1;
+ uint32_t fixed2;
+ uint32_t c;
+ uint32_t d;
+ uint32_t e;
+};
+
+#define SC1810C_CTL_LINE_SW 0
+#define SC1810C_CTL_MUTE_SW 1
+#define SC1810C_CTL_AB_SW 3
+#define SC1810C_CTL_48V_SW 4
+
+#define SC1810C_SET_STATE_REQ 161
+#define SC1810C_SET_STATE_REQTYPE SC1810C_CMD_REQTYPE
+#define SC1810C_SET_STATE_F1 0x64656D73
+#define SC1810C_SET_STATE_F2 0xF4
+
+#define SC1810C_GET_STATE_REQ 162
+#define SC1810C_GET_STATE_REQTYPE \
+ (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN)
+#define SC1810C_GET_STATE_F1 SC1810C_SET_STATE_F1
+#define SC1810C_GET_STATE_F2 SC1810C_SET_STATE_F2
+
+#define SC1810C_STATE_F1_IDX 2
+#define SC1810C_STATE_F2_IDX 3
+
+/*
+ * This packet includes mixer volumes and
+ * various other fields, it's an extended
+ * version of ctl_packet, with a and b
+ * being zero and different f1/f2.
+ */
+struct s1810c_state_packet {
+ uint32_t fields[63];
+};
+
+#define SC1810C_STATE_48V_SW 58
+#define SC1810C_STATE_LINE_SW 59
+#define SC1810C_STATE_MUTE_SW 60
+#define SC1810C_STATE_AB_SW 62
+
+struct s1810_mixer_state {
+ uint16_t seqnum;
+ struct mutex usb_mutex;
+};
+
+static int
+snd_s1810c_send_ctl_packet(struct usb_device *dev, uint32_t a,
+ uint32_t b, uint32_t c, uint32_t d, uint32_t e)
+{
+ struct s1810c_ctl_packet pkt = { 0 };
+ int ret = 0;
+
+ pkt.fixed1 = SC1810C_CMD_F1;
+ pkt.fixed2 = SC1810C_CMD_F2;
+
+ pkt.a = a;
+ pkt.b = b;
+ pkt.c = c;
+ pkt.d = d;
+ /*
+ * Value for settings 0/1 for this
+ * output channel is always 0 (probably because
+ * there is no ADAT output on 1810c)
+ */
+ pkt.e = (c == 4) ? 0 : e;
+
+ ret = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
+ SC1810C_CMD_REQ,
+ SC1810C_CMD_REQTYPE, 0, 0, &pkt, sizeof(pkt));
+ if (ret < 0) {
+ dev_warn(&dev->dev, "could not send ctl packet\n");
+ return ret;
+ }
+ return 0;
+}
+
+/*
+ * When opening Universal Control the program periodicaly
+ * sends and receives state packets for syncinc state between
+ * the device and the host.
+ *
+ * Note that if we send only the request to get data back we'll
+ * get an error, we need to first send an empty state packet and
+ * then ask to receive a filled. Their seqnumbers must also match.
+ */
+static int
+snd_sc1810c_get_status_field(struct usb_device *dev,
+ uint32_t *field, int field_idx, uint16_t *seqnum)
+{
+ struct s1810c_state_packet pkt_out = { 0 };
+ struct s1810c_state_packet pkt_in = { 0 };
+ int ret = 0;
+
+ pkt_out.fields[SC1810C_STATE_F1_IDX] = SC1810C_SET_STATE_F1;
+ pkt_out.fields[SC1810C_STATE_F2_IDX] = SC1810C_SET_STATE_F2;
+ ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
+ SC1810C_SET_STATE_REQ,
+ SC1810C_SET_STATE_REQTYPE,
+ (*seqnum), 0, &pkt_out, sizeof(pkt_out));
+ if (ret < 0) {
+ dev_warn(&dev->dev, "could not send state packet (%d)\n", ret);
+ return ret;
+ }
+
+ ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
+ SC1810C_GET_STATE_REQ,
+ SC1810C_GET_STATE_REQTYPE,
+ (*seqnum), 0, &pkt_in, sizeof(pkt_in));
+ if (ret < 0) {
+ dev_warn(&dev->dev, "could not get state field %u (%d)\n",
+ field_idx, ret);
+ return ret;
+ }
+
+ (*field) = pkt_in.fields[field_idx];
+ (*seqnum)++;
+ return 0;
+}
+
+/*
+ * This is what I got when bypassing the mixer with
+ * all channels split. I'm not 100% sure of what's going
+ * on, I could probably clean this up based on my observations
+ * but I prefer to keep the same behavior as the windows driver.
+ */
+static int snd_s1810c_init_mixer_maps(struct snd_usb_audio *chip)
+{
+ uint32_t a, b, c, e, n, off;
+ struct usb_device *dev = chip->dev;
+
+ /* Set initial volume levels ? */
+ a = 0x64;
+ e = 0xbc;
+ for (n = 0; n < 2; n++) {
+ off = n * 18;
+ for (b = off, c = 0; b < 18 + off; b++) {
+ /* This channel to all outputs ? */
+ for (c = 0; c <= 8; c++) {
+ snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e);
+ snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e);
+ }
+ /* This channel to main output (again) */
+ snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e);
+ snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e);
+ }
+ /*
+ * I noticed on UC that DAW channels have different
+ * initial volumes (they can go both above and below
+ * 0db), so this makes sense.
+ */
+ e = 0xb53bf0;
+ }
+
+ /* Connect analog outputs ? */
+ a = 0x65;
+ e = 0x01000000;
+ for (b = 1; b < 3; b++) {
+ snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e);
+ snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e);
+ }
+ snd_s1810c_send_ctl_packet(dev, a, 0, 0, 0, e);
+ snd_s1810c_send_ctl_packet(dev, a, 0, 0, 1, e);
+
+ /* Set initial volume levels for S/PDIF mappings ? */
+ a = 0x64;
+ e = 0xbc;
+ c = 3;
+ for (n = 0; n < 2; n++) {
+ off = n * 18;
+ for (b = off; b < 18 + off; b++) {
+ snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e);
+ snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e);
+ }
+ e = 0xb53bf0;
+ }
+
+ /* Connect S/PDIF output ? */
+ a = 0x65;
+ e = 0x01000000;
+ snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e);
+ snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e);
+
+ /* Connect all outputs (again) ? */
+ a = 0x65;
+ e = 0x01000000;
+ for (b = 0; b < 4; b++) {
+ snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e);
+ snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e);
+ }
+
+ /* Basic routing to get sound out of the device */
+ a = 0x64;
+ e = 0x01000000;
+ for (c = 0; c < 4; c++) {
+ for (b = 0; b < 36; b++) {
+ if ((c == 0 && b == 18) || /* DAW1/2 -> Main */
+ (c == 1 && b == 20) || /* DAW3/4 -> Line3/4 */
+ (c == 2 && b == 22) || /* DAW4/5 -> Line5/4 */
+ (c == 3 && b == 24)) { /* DAW5/6 -> S/PDIF */
+ /* Left */
+ snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e);
+ snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0);
+ b++;
+ /* Right */
+ snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0);
+ snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e);
+ } else {
+ /* Leave the rest disconnected */
+ snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0);
+ snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0);
+ }
+ }
+ }
+
+ /* Set initial volume levels for S/PDIF (again) ? */
+ a = 0x64;
+ e = 0xbc;
+ c = 3;
+ for (n = 0; n < 2; n++) {
+ off = n * 18;
+ for (b = off; b < 18 + off; b++) {
+ snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e);
+ snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e);
+ }
+ e = 0xb53bf0;
+ }
+
+ /* Connect S/PDIF outputs (again) ? */
+ a = 0x65;
+ e = 0x01000000;
+ snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e);
+ snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e);
+
+ /* Again ? */
+ snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e);
+ snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e);
+
+ return 0;
+}
+
+/*
+ * Sync state with the device and retrieve the requested field,
+ * whose index is specified in (kctl->private_value & 0xFF),
+ * from the received fields array.
+ */
+static int
+snd_s1810c_get_switch_state(struct usb_mixer_interface *mixer,
+ struct snd_kcontrol *kctl, uint32_t *state)
+{
+ struct snd_usb_audio *chip = mixer->chip;
+ struct s1810_mixer_state *private = mixer->private_data;
+ uint32_t field = 0;
+ uint32_t ctl_idx = (uint32_t) (kctl->private_value & 0xFF);
+ int ret = 0;
+
+ mutex_lock(&private->usb_mutex);
+ ret = snd_sc1810c_get_status_field(chip->dev, &field,
+ ctl_idx, &private->seqnum);
+ if (ret < 0)
+ goto unlock;
+
+ *state = field;
+ unlock:
+ mutex_unlock(&private->usb_mutex);
+ return ret ? ret : 0;
+}
+
+/*
+ * Send a control packet to the device for the control id
+ * specified in (kctl->private_value >> 8) with value
+ * specified in (kctl->private_value >> 16).
+ */
+static int
+snd_s1810c_set_switch_state(struct usb_mixer_interface *mixer,
+ struct snd_kcontrol *kctl)
+{
+ struct snd_usb_audio *chip = mixer->chip;
+ struct s1810_mixer_state *private = mixer->private_data;
+ uint32_t pval = (uint32_t) kctl->private_value;
+ uint32_t ctl_id = (pval >> 8) & 0xFF;
+ uint32_t ctl_val = (pval >> 16) & 0x1;
+ int ret = 0;
+
+ mutex_lock(&private->usb_mutex);
+ ret = snd_s1810c_send_ctl_packet(chip->dev, 0, 0, 0, ctl_id, ctl_val);
+ mutex_unlock(&private->usb_mutex);
+ return ret;
+}
+
+/* Generic get/set/init functions for switch controls */
+
+static int
+snd_s1810c_switch_get(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *ctl_elem)
+{
+ struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
+ struct usb_mixer_interface *mixer = list->mixer;
+ uint32_t state = 0;
+ int ret = 0;
+
+ ret = snd_s1810c_get_switch_state(mixer, kctl, &state);
+ if (ret < 0)
+ return ret;
+
+ ctl_elem->value.integer.value[0] = (long)state;
+
+ return 0;
+}
+
+static int
+snd_s1810c_switch_set(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *ctl_elem)
+{
+ struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
+ struct usb_mixer_interface *mixer = list->mixer;
+ uint32_t curval = 0;
+ uint32_t newval = (uint32_t) ctl_elem->value.integer.value[0];
+ int ret = 0;
+
+ ret = snd_s1810c_get_switch_state(mixer, kctl, &curval);
+ if (ret < 0)
+ return 0;
+
+ if (curval == newval)
+ return 0;
+
+ kctl->private_value &= ~(0x1 << 16);
+ kctl->private_value |= (unsigned int)(newval & 0x1) << 16;
+ ret = snd_s1810c_set_switch_state(mixer, kctl);
+ if (ret < 0)
+ return 0;
+
+ return 1;
+}
+
+static int
+snd_s1810c_switch_init(struct usb_mixer_interface *mixer,
+ const struct snd_kcontrol_new *new_kctl)
+{
+ struct snd_kcontrol *kctl;
+ struct usb_mixer_elem_info *elem;
+
+ elem = kzalloc(sizeof(struct usb_mixer_elem_info), GFP_KERNEL);
+ if (!elem)
+ return -ENOMEM;
+
+ elem->head.mixer = mixer;
+ elem->control = 0;
+ elem->head.id = 0;
+ elem->channels = 1;
+
+ kctl = snd_ctl_new1(new_kctl, elem);
+ if (!kctl) {
+ kfree(elem);
+ return -ENOMEM;
+ }
+ kctl->private_free = snd_usb_mixer_elem_free;
+
+ return snd_usb_mixer_add_control(&elem->head, kctl);
+}
+
+static int
+snd_s1810c_line_sw_info(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static const char *const texts[2] = { "Preamp on (Mic/Inst)",
+ "Preamp off (Line in)"
+ };
+
+ return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
+}
+
+static struct snd_kcontrol_new snd_s1810c_line_sw = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Line 1/2 source type",
+ .info = snd_s1810c_line_sw_info,
+ .get = snd_s1810c_switch_get,
+ .put = snd_s1810c_switch_set,
+ .private_value = (SC1810C_STATE_LINE_SW | SC1810C_CTL_LINE_SW << 8)
+};
+
+static struct snd_kcontrol_new snd_s1810c_mute_sw = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mute Main Out",
+ .info = snd_ctl_boolean_mono_info,
+ .get = snd_s1810c_switch_get,
+ .put = snd_s1810c_switch_set,
+ .private_value = (SC1810C_STATE_MUTE_SW | SC1810C_CTL_MUTE_SW << 8)
+};
+
+static struct snd_kcontrol_new snd_s1810c_48v_sw = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "48V Phantom power on Mic inputs",
+ .info = snd_ctl_boolean_mono_info,
+ .get = snd_s1810c_switch_get,
+ .put = snd_s1810c_switch_set,
+ .private_value = (SC1810C_STATE_48V_SW | SC1810C_CTL_48V_SW << 8)
+};
+
+static int
+snd_s1810c_ab_sw_info(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static const char *const texts[2] = { "1/2",
+ "3/4"
+ };
+
+ return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
+}
+
+static struct snd_kcontrol_new snd_s1810c_ab_sw = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Headphone 1 source selector",
+ .info = snd_s1810c_ab_sw_info,
+ .get = snd_s1810c_switch_get,
+ .put = snd_s1810c_switch_set,
+ .private_value = (SC1810C_STATE_AB_SW | SC1810C_CTL_AB_SW << 8)
+};
+
+static void snd_sc1810_mixer_state_free(struct usb_mixer_interface *mixer)
+{
+ struct s1810_mixer_state *private = mixer->private_data;
+ vfree(private);
+ mixer->private_data = NULL;
+}
+
+/* Entry point, called from mixer_quirks.c */
+int snd_sc1810_init_mixer(struct usb_mixer_interface *mixer)
+{
+ struct s1810_mixer_state *private = NULL;
+ struct snd_usb_audio *chip = mixer->chip;
+ struct usb_device *dev = chip->dev;
+ int ret = 0;
+
+ /* Run this only once */
+ if (!list_empty(&chip->mixer_list))
+ return 0;
+
+ dev_info(&dev->dev,
+ "Presonus Studio 1810c, device_setup: %u\n", chip->setup);
+ if (chip->setup == 1)
+ dev_info(&dev->dev, "(8out/18in @ 48KHz)\n");
+ else if (chip->setup == 2)
+ dev_info(&dev->dev, "(6out/8in @ 192KHz)\n");
+ else
+ dev_info(&dev->dev, "(8out/14in @ 96KHz)\n");
+
+ ret = snd_s1810c_init_mixer_maps(chip);
+ if (ret < 0)
+ return ret;
+
+ private = vzalloc(sizeof(struct s1810_mixer_state));
+ if (!private) {
+ dev_err(&dev->dev, "could not allocate mixer state\n");
+ return -ENOMEM;
+ }
+
+ mutex_init(&private->usb_mutex);
+
+ mixer->private_data = private;
+ mixer->private_free = snd_sc1810_mixer_state_free;
+
+ private->seqnum = 1;
+
+ ret = snd_s1810c_switch_init(mixer, &snd_s1810c_line_sw);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_s1810c_switch_init(mixer, &snd_s1810c_mute_sw);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_s1810c_switch_init(mixer, &snd_s1810c_48v_sw);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_s1810c_switch_init(mixer, &snd_s1810c_ab_sw);
+ if (ret < 0)
+ return ret;
+ return ret;
+}
diff --git a/sound/usb/mixer_s1810c.h b/sound/usb/mixer_s1810c.h
new file mode 100644
index 000000000..2a9ae0922
--- /dev/null
+++ b/sound/usb/mixer_s1810c.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Presonus Studio 1810c driver for ALSA
+ * Copyright (C) 2019 Nick Kossifidis <mickflemm(a)gmail.com>
+ */
+int snd_sc1810_init_mixer(struct usb_mixer_interface *mixer);
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 349e1e529..9a0ceaaf9 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1216,6 +1216,36 @@ static int fasttrackpro_skip_setting_quirk(struct snd_usb_audio *chip,
return 0; /* keep this altsetting */
}
+static int s1810c_skip_setting_quirk(struct snd_usb_audio *chip,
+ int iface, int altno)
+{
+ /*
+ * Playback:
+ * 1: 6 Analog + 2 S/PDIF
+ * 2: 6 Analog + 2 S/PDIF
+ * 3: 6 Analog
+ *
+ * Capture:
+ * 1: 8 Analog + 2 S/PDIF + 8 ADAT
+ * 2: 8 Analog + 2 S/PDIF + 4 ADAT
+ * 3: 8 Analog
+ */
+
+ /*
+ * I'll leave 2 as the default one and
+ * use device_setup to switch to the
+ * other two.
+ */
+ if (chip->setup == 1 && altno != 1)
+ return 1;
+ else if (chip->setup == 2 && altno != 3)
+ return 1;
+ else if (altno != 2)
+ return 1;
+
+ return 0;
+}
+
int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip,
int iface,
int altno)
@@ -1229,6 +1259,10 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip,
/* fasttrackpro usb: skip altsets incompatible with device_setup */
if (chip->usb_id == USB_ID(0x0763, 0x2012))
return fasttrackpro_skip_setting_quirk(chip, iface, altno);
+ /* presonus studio 1810c: skip altsets incompatible with device_setup */
+ if (chip->usb_id == USB_ID(0x0194f, 0x010c))
+ return s1810c_skip_setting_quirk(chip, iface, altno);
+
return 0;
}
--
2.23.0
1
0
[alsa-devel] [PATCH] ASoC: SOF: imx8: fix memory allocation failure check on priv->pd_dev
by Colin King 25 Dec '19
by Colin King 25 Dec '19
25 Dec '19
From: Colin Ian King <colin.king(a)canonical.com>
The memory allocation failure check for priv->pd_dev is incorrectly
pointer checking priv instead of priv->pd_dev. Fix this.
Addresses-Coverity: ("Logically dead code")
Fixes: 202acc565a1f ("ASoC: SOF: imx: Add i.MX8 HW support")
Signed-off-by: Colin Ian King <colin.king(a)canonical.com>
---
sound/soc/sof/imx/imx8.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c
index cfefcfd92798..9d926b1df0d7 100644
--- a/sound/soc/sof/imx/imx8.c
+++ b/sound/soc/sof/imx/imx8.c
@@ -209,7 +209,7 @@ static int imx8_probe(struct snd_sof_dev *sdev)
priv->pd_dev = devm_kmalloc_array(&pdev->dev, priv->num_domains,
sizeof(*priv->pd_dev), GFP_KERNEL);
- if (!priv)
+ if (!priv->pd_dev)
return -ENOMEM;
priv->link = devm_kmalloc_array(&pdev->dev, priv->num_domains,
--
2.24.0
4
3
25 Dec '19
When converting a normal link to a DPCM link we need
to set dpcm_playback / dpcm_capture otherwise playback/capture
streams will not be created resulting in errors like this:
[ 36.039111] sai1-wm8960-hifi: ASoC: no backend playback stream
Fixes: a655de808cbde ("ASoC: core: Allow topology to override machine driver FE DAI link config")
Signed-off-by: Daniel Baluta <daniel.baluta(a)nxp.com>
---
sound/soc/soc-core.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 977a7bfad519..f89cf9d0860c 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1872,6 +1872,8 @@ static void soc_check_tplg_fes(struct snd_soc_card *card)
/* convert non BE into BE */
dai_link->no_pcm = 1;
+ dai_link->dpcm_playback = 1;
+ dai_link->dpcm_capture = 1;
/* override any BE fixups */
dai_link->be_hw_params_fixup =
--
2.17.1
5
4
25 Dec '19
This patchset fixes some race conditions on STM32 SPDIFRX driver.
Olivier Moysan (3):
ASoC: stm32: spdifrx: fix inconsistent lock state
ASoC: stm32: spdifrx: fix race condition in irq handler
ASoC: stm32: spdifrx: fix input pin state management
sound/soc/stm/stm32_spdifrx.c | 40 +++++++++++++++++++++++------------
1 file changed, 26 insertions(+), 14 deletions(-)
--
2.17.1
2
6