Browse Source

asoc: bolero: Add EC support for WSA macro

WSA macro supports both ec_legacy and ec_hq.
Add support to capture echo for both types
based on mixer control value.

Change-Id: I3c8a6cd13dabbee3f3687d5e63dc6d4c7bbc4eef
Signed-off-by: Laxminath Kasam <[email protected]>
Laxminath Kasam 6 years ago
parent
commit
36ab7bb29c
1 changed files with 124 additions and 0 deletions
  1. 124 0
      asoc/codecs/bolero/wsa-macro.c

+ 124 - 0
asoc/codecs/bolero/wsa-macro.c

@@ -70,6 +70,12 @@ enum {
 	WSA_MACRO_TX_MAX,
 };
 
+enum {
+	WSA_MACRO_EC0_MUX = 0,
+	WSA_MACRO_EC1_MUX,
+	WSA_MACRO_EC_MUX_MAX,
+};
+
 enum {
 	WSA_MACRO_COMP1, /* SPK_L */
 	WSA_MACRO_COMP2, /* SPK_R */
@@ -148,6 +154,7 @@ enum {
 /*
  * @dev: wsa macro device pointer
  * @comp_enabled: compander enable mixer value set
+ * @ec_hq: echo HQ enable mixer value set
  * @prim_int_users: Users of interpolator
  * @wsa_mclk_users: WSA MCLK users count
  * @swr_clk_users: SWR clk users count
@@ -171,6 +178,7 @@ enum {
 struct wsa_macro_priv {
 	struct device *dev;
 	int comp_enabled[WSA_MACRO_COMP_MAX];
+	int ec_hq[WSA_MACRO_RX1 + 1];
 	u16 prim_int_users[WSA_MACRO_RX1 + 1];
 	u16 wsa_mclk_users;
 	u16 swr_clk_users;
@@ -212,6 +220,10 @@ static const char *const rx_mix_text[] = {
 	"ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1"
 };
 
+static const char *const rx_mix_ec_text[] = {
+	"ZERO", "RX_MIX_TX0", "RX_MIX_TX1"
+};
+
 static const char *const rx_mux_text[] = {
 	"ZERO", "AIF1_PB", "AIF_MIX1_PB"
 };
@@ -288,6 +300,20 @@ static const struct snd_kcontrol_new rx1_prim_inp2_mux =
 static const struct snd_kcontrol_new rx1_mix_mux =
 	SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum);
 
+static const struct soc_enum rx_mix_ec0_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
+		0, 3, rx_mix_ec_text);
+
+static const struct soc_enum rx_mix_ec1_enum =
+	SOC_ENUM_SINGLE(BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
+		3, 3, rx_mix_ec_text);
+
+static const struct snd_kcontrol_new rx_mix_ec0_mux =
+	SOC_DAPM_ENUM("WSA RX_MIX EC0_Mux", rx_mix_ec0_enum);
+
+static const struct snd_kcontrol_new rx_mix_ec1_mux =
+	SOC_DAPM_ENUM("WSA RX_MIX EC1_Mux", rx_mix_ec1_enum);
+
 static struct snd_soc_dai_ops wsa_macro_dai_ops = {
 	.hw_params = wsa_macro_hw_params,
 	.get_channel_map = wsa_macro_get_channel_map,
@@ -1317,6 +1343,84 @@ static int wsa_macro_spk_boost_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static int wsa_macro_enable_echo(struct snd_soc_dapm_widget *w,
+				 struct snd_kcontrol *kcontrol,
+				 int event)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+	u16 val, ec_tx = 0, ec_hq_reg;
+
+	if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(wsa_dev, "%s %d %s\n", __func__, event, w->name);
+
+	val = snd_soc_read(codec, BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0);
+	if (!(strcmp(w->name, "WSA RX_MIX EC0_MUX")))
+		ec_tx = (val & 0x07) - 1;
+	else
+		ec_tx = ((val & 0x38) >> 0x3) - 1;
+
+	if (ec_tx < 0 || ec_tx >= (WSA_MACRO_RX1 + 1)) {
+		dev_err(wsa_dev, "%s: EC mix control not set correctly\n",
+			__func__);
+		return -EINVAL;
+	}
+	if (wsa_priv->ec_hq[ec_tx]) {
+		snd_soc_update_bits(codec,
+				BOLERO_CDC_WSA_RX_INP_MUX_RX_MIX_CFG0,
+				0x1 << ec_tx, 0x1 << ec_tx);
+		ec_hq_reg = BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL +
+							0x20 * ec_tx;
+		snd_soc_update_bits(codec, ec_hq_reg, 0x01, 0x01);
+		ec_hq_reg = BOLERO_CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0 +
+							0x20 * ec_tx;
+		/* default set to 48k */
+		snd_soc_update_bits(codec, ec_hq_reg, 0x1E, 0x08);
+	}
+
+	return 0;
+}
+
+static int wsa_macro_get_ec_hq(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	int ec_tx = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = wsa_priv->ec_hq[ec_tx];
+	return 0;
+}
+
+static int wsa_macro_set_ec_hq(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+	int ec_tx = ((struct soc_multi_mixer_control *)
+		    kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+	struct device *wsa_dev = NULL;
+	struct wsa_macro_priv *wsa_priv = NULL;
+
+	if (!wsa_macro_get_data(codec, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(wsa_dev, "%s: enable current %d, new %d\n",
+		__func__, wsa_priv->ec_hq[ec_tx], value);
+	wsa_priv->ec_hq[ec_tx] = value;
+
+	return 0;
+}
+
 static int wsa_macro_get_compander(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
@@ -1542,6 +1646,10 @@ static const struct snd_kcontrol_new wsa_macro_snd_controls[] = {
 		wsa_macro_get_compander, wsa_macro_set_compander),
 	SOC_SINGLE_EXT("WSA_COMP2 Switch", SND_SOC_NOPM, WSA_MACRO_COMP2, 1, 0,
 		wsa_macro_get_compander, wsa_macro_set_compander),
+	SOC_SINGLE_EXT("WSA_RX0 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX0,
+			1, 0, wsa_macro_get_ec_hq, wsa_macro_set_ec_hq),
+	SOC_SINGLE_EXT("WSA_RX1 EC_HQ Switch", SND_SOC_NOPM, WSA_MACRO_RX1,
+			1, 0, wsa_macro_get_ec_hq, wsa_macro_set_ec_hq),
 };
 
 static const struct soc_enum rx_mux_enum =
@@ -1662,6 +1770,14 @@ static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
 
 	SND_SOC_DAPM_MIXER("WSA_AIF_VI Mixer", SND_SOC_NOPM, WSA_MACRO_AIF_VI,
 		0, aif_vi_mixer, ARRAY_SIZE(aif_vi_mixer)),
+	SND_SOC_DAPM_MUX_E("WSA RX_MIX EC0_MUX", SND_SOC_NOPM,
+			WSA_MACRO_EC0_MUX, 0,
+			&rx_mix_ec0_mux, wsa_macro_enable_echo,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MUX_E("WSA RX_MIX EC1_MUX", SND_SOC_NOPM,
+			WSA_MACRO_EC1_MUX, 0,
+			&rx_mix_ec1_mux, wsa_macro_enable_echo,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX("WSA RX0 MUX", SND_SOC_NOPM, WSA_MACRO_RX0, 0,
 				&rx_mux[WSA_MACRO_RX0]),
@@ -1738,6 +1854,14 @@ static const struct snd_soc_dapm_route wsa_audio_map[] = {
 	{"WSA AIF_VI", NULL, "WSA_AIF_VI Mixer"},
 	{"WSA AIF_VI", NULL, "WSA_MCLK"},
 
+	{"WSA RX_MIX EC0_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
+	{"WSA RX_MIX EC1_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
+	{"WSA RX_MIX EC0_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
+	{"WSA RX_MIX EC1_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
+	{"WSA AIF_ECHO", NULL, "WSA RX_MIX EC0_MUX"},
+	{"WSA AIF_ECHO", NULL, "WSA RX_MIX EC1_MUX"},
+	{"WSA AIF_ECHO", NULL, "WSA_MCLK"},
+
 	{"WSA AIF1 PB", NULL, "WSA_MCLK"},
 	{"WSA AIF_MIX1 PB", NULL, "WSA_MCLK"},