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 <lkasam@codeaurora.org>
This commit is contained in:
Laxminath Kasam
2018-06-18 18:43:46 +05:30
parent cf05e6d33c
commit 36ab7bb29c

View File

@@ -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"},