mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 20:24:12 +08:00
ASoC: codecs: wcd937x: add basic controls
This patch adds basic controls found in WCD9370/WCD9375 codec. Signed-off-by: Prasad Kumpatla <quic_pkumpatl@quicinc.com> Co-developed-by: Mohammad Rafi Shaik <quic_mohs@quicinc.com> Signed-off-by: Mohammad Rafi Shaik <quic_mohs@quicinc.com> Link: https://lore.kernel.org/r/20240524035535.3119208-5-quic_mohs@quicinc.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
9be3ec196d
commit
82be8c62a3
@ -120,6 +120,10 @@ struct wcd937x_priv {
|
||||
atomic_t ana_clk_count;
|
||||
};
|
||||
|
||||
static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800);
|
||||
static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
|
||||
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
|
||||
|
||||
struct wcd937x_mbhc_zdet_param {
|
||||
u16 ldo_ctl;
|
||||
u16 noff;
|
||||
@ -476,6 +480,157 @@ static int wcd937x_connect_port(struct wcd937x_sdw_priv *wcd, u8 port_idx, u8 ch
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd937x_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
|
||||
|
||||
ucontrol->value.integer.value[0] = wcd937x->hph_mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd937x_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component =
|
||||
snd_soc_kcontrol_component(kcontrol);
|
||||
struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
|
||||
u32 mode_val;
|
||||
|
||||
mode_val = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (!mode_val)
|
||||
mode_val = CLS_AB;
|
||||
|
||||
if (mode_val == wcd937x->hph_mode)
|
||||
return 0;
|
||||
|
||||
switch (mode_val) {
|
||||
case CLS_H_NORMAL:
|
||||
case CLS_H_HIFI:
|
||||
case CLS_H_LP:
|
||||
case CLS_AB:
|
||||
case CLS_H_LOHIFI:
|
||||
case CLS_H_ULP:
|
||||
case CLS_AB_LP:
|
||||
case CLS_AB_HIFI:
|
||||
wcd937x->hph_mode = mode_val;
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev_dbg(component->dev, "%s: Invalid HPH Mode\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int wcd937x_get_compander(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
|
||||
struct soc_mixer_control *mc;
|
||||
bool hphr;
|
||||
|
||||
mc = (struct soc_mixer_control *)(kcontrol->private_value);
|
||||
hphr = mc->shift;
|
||||
|
||||
ucontrol->value.integer.value[0] = hphr ? wcd937x->comp2_enable :
|
||||
wcd937x->comp1_enable;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd937x_set_compander(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
|
||||
struct wcd937x_sdw_priv *wcd = wcd937x->sdw_priv[AIF1_PB];
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
struct soc_mixer_control *mc;
|
||||
int portidx;
|
||||
bool hphr;
|
||||
|
||||
mc = (struct soc_mixer_control *)(kcontrol->private_value);
|
||||
hphr = mc->shift;
|
||||
|
||||
if (hphr) {
|
||||
if (value == wcd937x->comp2_enable)
|
||||
return 0;
|
||||
|
||||
wcd937x->comp2_enable = value;
|
||||
} else {
|
||||
if (value == wcd937x->comp1_enable)
|
||||
return 0;
|
||||
|
||||
wcd937x->comp1_enable = value;
|
||||
}
|
||||
|
||||
portidx = wcd->ch_info[mc->reg].port_num;
|
||||
|
||||
if (value)
|
||||
wcd937x_connect_port(wcd, portidx, mc->reg, true);
|
||||
else
|
||||
wcd937x_connect_port(wcd, portidx, mc->reg, false);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int wcd937x_get_swr_port(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value;
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(comp);
|
||||
struct wcd937x_sdw_priv *wcd;
|
||||
int dai_id = mixer->shift;
|
||||
int ch_idx = mixer->reg;
|
||||
int portidx;
|
||||
|
||||
wcd = wcd937x->sdw_priv[dai_id];
|
||||
portidx = wcd->ch_info[ch_idx].port_num;
|
||||
|
||||
ucontrol->value.integer.value[0] = wcd->port_enable[portidx];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd937x_set_swr_port(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct soc_mixer_control *mixer = (struct soc_mixer_control *)kcontrol->private_value;
|
||||
struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol);
|
||||
struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(comp);
|
||||
struct wcd937x_sdw_priv *wcd;
|
||||
int dai_id = mixer->shift;
|
||||
int ch_idx = mixer->reg;
|
||||
int portidx;
|
||||
bool enable;
|
||||
|
||||
wcd = wcd937x->sdw_priv[dai_id];
|
||||
|
||||
portidx = wcd->ch_info[ch_idx].port_num;
|
||||
|
||||
enable = ucontrol->value.integer.value[0];
|
||||
|
||||
if (enable == wcd->port_enable[portidx]) {
|
||||
wcd937x_connect_port(wcd, portidx, ch_idx, enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wcd->port_enable[portidx] = enable;
|
||||
wcd937x_connect_port(wcd, portidx, ch_idx, enable);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char * const rx_hph_mode_mux_text[] = {
|
||||
"CLS_H_NORMAL", "CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB",
|
||||
"CLS_H_LOHIFI", "CLS_H_ULP", "CLS_AB_LP", "CLS_AB_HIFI",
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
/* MBHC related */
|
||||
static void wcd937x_mbhc_clk_setup(struct snd_soc_component *component,
|
||||
bool enable)
|
||||
@ -1150,6 +1305,50 @@ static void wcd937x_mbhc_deinit(struct snd_soc_component *component)
|
||||
|
||||
/* END MBHC */
|
||||
|
||||
static const struct snd_kcontrol_new wcd937x_snd_controls[] = {
|
||||
SOC_SINGLE_TLV("EAR_PA Volume", WCD937X_ANA_EAR_COMPANDER_CTL,
|
||||
2, 0x10, 0, ear_pa_gain),
|
||||
SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,
|
||||
wcd937x_rx_hph_mode_get, wcd937x_rx_hph_mode_put),
|
||||
|
||||
SOC_SINGLE_EXT("HPHL_COMP Switch", SND_SOC_NOPM, 0, 1, 0,
|
||||
wcd937x_get_compander, wcd937x_set_compander),
|
||||
SOC_SINGLE_EXT("HPHR_COMP Switch", SND_SOC_NOPM, 1, 1, 0,
|
||||
wcd937x_get_compander, wcd937x_set_compander),
|
||||
|
||||
SOC_SINGLE_TLV("HPHL Volume", WCD937X_HPH_L_EN, 0, 20, 1, line_gain),
|
||||
SOC_SINGLE_TLV("HPHR Volume", WCD937X_HPH_R_EN, 0, 20, 1, line_gain),
|
||||
SOC_SINGLE_TLV("ADC1 Volume", WCD937X_ANA_TX_CH1, 0, 20, 0, analog_gain),
|
||||
SOC_SINGLE_TLV("ADC2 Volume", WCD937X_ANA_TX_CH2, 0, 20, 0, analog_gain),
|
||||
SOC_SINGLE_TLV("ADC3 Volume", WCD937X_ANA_TX_CH3, 0, 20, 0, analog_gain),
|
||||
|
||||
SOC_SINGLE_EXT("HPHL Switch", WCD937X_HPH_L, 0, 1, 0,
|
||||
wcd937x_get_swr_port, wcd937x_set_swr_port),
|
||||
SOC_SINGLE_EXT("HPHR Switch", WCD937X_HPH_R, 0, 1, 0,
|
||||
wcd937x_get_swr_port, wcd937x_set_swr_port),
|
||||
|
||||
SOC_SINGLE_EXT("ADC1 Switch", WCD937X_ADC1, 1, 1, 0,
|
||||
wcd937x_get_swr_port, wcd937x_set_swr_port),
|
||||
SOC_SINGLE_EXT("ADC2 Switch", WCD937X_ADC2, 1, 1, 0,
|
||||
wcd937x_get_swr_port, wcd937x_set_swr_port),
|
||||
SOC_SINGLE_EXT("ADC3 Switch", WCD937X_ADC3, 1, 1, 0,
|
||||
wcd937x_get_swr_port, wcd937x_set_swr_port),
|
||||
SOC_SINGLE_EXT("DMIC0 Switch", WCD937X_DMIC0, 1, 1, 0,
|
||||
wcd937x_get_swr_port, wcd937x_set_swr_port),
|
||||
SOC_SINGLE_EXT("DMIC1 Switch", WCD937X_DMIC1, 1, 1, 0,
|
||||
wcd937x_get_swr_port, wcd937x_set_swr_port),
|
||||
SOC_SINGLE_EXT("MBHC Switch", WCD937X_MBHC, 1, 1, 0,
|
||||
wcd937x_get_swr_port, wcd937x_set_swr_port),
|
||||
SOC_SINGLE_EXT("DMIC2 Switch", WCD937X_DMIC2, 1, 1, 0,
|
||||
wcd937x_get_swr_port, wcd937x_set_swr_port),
|
||||
SOC_SINGLE_EXT("DMIC3 Switch", WCD937X_DMIC3, 1, 1, 0,
|
||||
wcd937x_get_swr_port, wcd937x_set_swr_port),
|
||||
SOC_SINGLE_EXT("DMIC4 Switch", WCD937X_DMIC4, 1, 1, 0,
|
||||
wcd937x_get_swr_port, wcd937x_set_swr_port),
|
||||
SOC_SINGLE_EXT("DMIC5 Switch", WCD937X_DMIC5, 1, 1, 0,
|
||||
wcd937x_get_swr_port, wcd937x_set_swr_port),
|
||||
};
|
||||
|
||||
static int wcd937x_set_micbias_data(struct wcd937x_priv *wcd937x)
|
||||
{
|
||||
int vout_ctl[3];
|
||||
@ -1316,6 +1515,8 @@ static const struct snd_soc_component_driver soc_codec_dev_wcd937x = {
|
||||
.name = "wcd937x_codec",
|
||||
.probe = wcd937x_soc_codec_probe,
|
||||
.remove = wcd937x_soc_codec_remove,
|
||||
.controls = wcd937x_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(wcd937x_snd_controls),
|
||||
.set_jack = wcd937x_codec_set_jack,
|
||||
.endianness = 1,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user