asoc: codecs: add support for xtalk

add support for xtalk on wcd939x.

Change-Id: I3aac6196363f2032e8ff453ca3cf52143bafcd0e
Signed-off-by: Prasad Kumpatla <quic_pkumpatl@quicinc.com>
This commit is contained in:
Prasad Kumpatla
2022-09-01 11:01:37 +05:30
committed by Gerrit - the friendly Code Review server
parent d0220474be
commit 76f60e792b
2 changed files with 117 additions and 11 deletions

View File

@@ -81,8 +81,9 @@ struct wcd939x_priv {
/* mbhc module */
struct wcd939x_mbhc *mbhc;
/*comp and xtalk*/
/*compander and xtalk*/
int compander_enabled[WCD939X_HPH_MAX];
int xtalk_enabled[WCD939X_HPH_MAX];
u32 hph_mode;
u32 tx_mode[TX_ADC_MAX];

View File

@@ -70,6 +70,9 @@ value << FIELD_SHIFT(register_name, field_name)
#define WCD939X_COMP_OFFSET \
(WCD939X_R_BASE - WCD939X_COMPANDER_HPHL_BASE)
#define WCD939X_XTALK_OFFSET \
(WCD939X_HPHR_RX_PATH_SEC0 - WCD939X_HPHL_RX_PATH_SEC0)
enum {
HPH_ULP,
HPH_HIFI,
@@ -295,6 +298,47 @@ static int wcd939x_hph_compander_put(struct snd_kcontrol *kcontrol,
return 0;
}
static int wcd939x_hph_xtalk_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component);
int xtalk = ((struct soc_multi_mixer_control *)
kcontrol->private_value)->shift;
int value = ucontrol->value.integer.value[0];
if (value < WCD939X_HPH_MAX && value >= 0)
wcd939x->xtalk_enabled[xtalk] = value;
else {
dev_err(component->dev, "%s: Invalid xtalk value = %d\n", __func__, value);
return -EINVAL;
}
dev_dbg(component->dev, "%s: xtalk %d value %d\n",
__func__, wcd939x->xtalk_enabled[xtalk], value);
return 0;
}
static int wcd939x_hph_xtalk_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component);
int xtalk = ((struct soc_multi_mixer_control *)
kcontrol->private_value)->shift;
ucontrol->value.integer.value[0] = wcd939x->xtalk_enabled[xtalk];
return 0;
}
static int wcd939x_swr_slv_get_current_bank(struct swr_device *dev, u8 devnum)
{
int ret = 0;
@@ -845,6 +889,55 @@ static int wcd939x_config_compander(struct snd_soc_component *component,
return 0;
}
static int wcd939x_config_xtalk(struct snd_soc_component *component,
int event, int xtalk_indx)
{
u16 xtalk_sec0 = 0, xtalk_sec1 = 0, xtalk_sec2 = 0, xtalk_sec3 = 0;
struct wcd939x_priv *wcd939x = NULL;
if (!component) {
pr_err_ratelimited("%s: Invalid params, NULL component\n", __func__);
return -EINVAL;
}
wcd939x = snd_soc_component_get_drvdata(component);
if (!wcd939x->xtalk_enabled[xtalk_indx])
return 0;
dev_dbg(component->dev, "%s xtalk_indx = %d event = %d\n",
__func__, xtalk_indx, event);
switch(event) {
case SND_SOC_DAPM_PRE_PMU:
xtalk_sec0 = WCD939X_HPHL_RX_PATH_SEC0 + (xtalk_indx * WCD939X_XTALK_OFFSET);
xtalk_sec1 = WCD939X_HPHL_RX_PATH_SEC1 + (xtalk_indx * WCD939X_XTALK_OFFSET);
xtalk_sec2 = WCD939X_HPHL_RX_PATH_SEC2 + (xtalk_indx * WCD939X_XTALK_OFFSET);
xtalk_sec3 = WCD939X_HPHL_RX_PATH_SEC3 + (xtalk_indx * WCD939X_XTALK_OFFSET);
snd_soc_component_update_bits(component, xtalk_sec1, 0xFF, 0xFE);
snd_soc_component_update_bits(component, xtalk_sec0, 0x1F, 0x06);
snd_soc_component_update_bits(component, xtalk_sec3, 0xFF, 0x4F);
snd_soc_component_update_bits(component, xtalk_sec2, 0x1F, 0x11);
break;
case SND_SOC_DAPM_POST_PMU:
/* enable xtalk for L and R channels*/
snd_soc_component_update_bits(component, WCD939X_RX_PATH_CFG2,
0x0F, 0x0F);
break;
case SND_SOC_DAPM_POST_PMD:
/* Disable Xtalk for L and R channels*/
snd_soc_component_update_bits(component, WCD939X_RX_PATH_CFG2,
0x00, 0x00);
break;
}
return 0;
}
static int wcd939x_rx_mux(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
@@ -859,9 +952,14 @@ static int wcd939x_rx_mux(struct snd_soc_dapm_widget *w,
case SND_SOC_DAPM_PRE_PMU:
wcd939x_rx_clk_enable(component);
wcd939x_config_compander(component, event, w->shift);
wcd939x_config_xtalk(component, event, w->shift);
break;
case SND_SOC_DAPM_POST_PMU:
wcd939x_config_xtalk(component, event, w->shift);
break;
case SND_SOC_DAPM_POST_PMD:
wcd939x_rx_clk_disable(component);
wcd939x_config_xtalk(component, event, w->shift);
wcd939x_config_compander(component, event, w->shift);
break;
@@ -3187,6 +3285,11 @@ static const struct snd_kcontrol_new wcd939x_snd_controls[] = {
SOC_SINGLE_EXT("HPHR Compander", SND_SOC_NOPM, WCD939X_HPHR, 1, 0,
wcd939x_hph_compander_get, wcd939x_hph_compander_put),
SOC_SINGLE_EXT("HPHL XTALK", SND_SOC_NOPM, WCD939X_HPHL, 1, 0,
wcd939x_hph_xtalk_get, wcd939x_hph_xtalk_put),
SOC_SINGLE_EXT("HPHR XTALK", SND_SOC_NOPM, WCD939X_HPHR, 1, 0,
wcd939x_hph_xtalk_get, wcd939x_hph_xtalk_put),
SOC_ENUM_EXT("ADC1 ChMap", tx_master_ch_enum,
wcd939x_tx_master_ch_get, wcd939x_tx_master_ch_put),
SOC_ENUM_EXT("ADC2 ChMap", tx_master_ch_enum,
@@ -3375,19 +3478,19 @@ static const struct snd_kcontrol_new rx_rdac3_mux =
static const char * const rx1_mux_text[] = {
"ZERO", "RX1 MUX"
};
static const struct soc_enum rx_rx1_enum =
static const struct soc_enum rx1_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 0, rx1_mux_text);
static const struct snd_kcontrol_new rx_rx1_mux =
SOC_DAPM_ENUM("RX1 MUX Mux", rx_rx1_enum);
static const struct snd_kcontrol_new rx1_mux =
SOC_DAPM_ENUM("RX1 MUX Mux", rx1_enum);
static const char * const rx2_mux_text[] = {
"ZERO", "RX2 MUX"
};
static const struct soc_enum rx_rx2_enum =
static const struct soc_enum rx2_enum =
SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 0, rx2_mux_text);
static const struct snd_kcontrol_new rx_rx2_mux =
SOC_DAPM_ENUM("RX2 MUX Mux", rx_rx2_enum);
static const struct snd_kcontrol_new rx2_mux =
SOC_DAPM_ENUM("RX2 MUX Mux", rx2_enum);
static const struct snd_soc_dapm_widget wcd939x_dapm_widgets[] = {
@@ -3618,10 +3721,12 @@ static const struct snd_soc_dapm_widget wcd939x_dapm_widgets[] = {
SND_SOC_DAPM_MUX("RDAC3_MUX", SND_SOC_NOPM, 0, 0, &rx_rdac3_mux),
SND_SOC_DAPM_MUX_E("RX1 MUX", SND_SOC_NOPM, WCD_RX1, 0, &rx_rx1_mux,
wcd939x_rx_mux, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("RX2 MUX", SND_SOC_NOPM, WCD_RX2, 0, &rx_rx2_mux,
wcd939x_rx_mux, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("RX1 MUX", SND_SOC_NOPM, WCD_RX1, 0, &rx1_mux,
wcd939x_rx_mux, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU
| SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("RX2 MUX", SND_SOC_NOPM, WCD_RX2, 0, &rx2_mux,
wcd939x_rx_mux, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU
| SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MIXER_E("RX1", SND_SOC_NOPM, 0, 0, NULL, 0,
wcd939x_enable_rx1, SND_SOC_DAPM_PRE_PMU |