forked from Minki/linux
ASoC: wcd9335: add basic controls
This patch adds basic controls found in wcd9335 codec. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Reviewed-by: Vinod Koul <vkoul@kernel.org> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
cc2e324d39
commit
8c4f021d80
@ -105,6 +105,18 @@ enum {
|
||||
NUM_CODEC_DAIS,
|
||||
};
|
||||
|
||||
enum {
|
||||
COMPANDER_1, /* HPH_L */
|
||||
COMPANDER_2, /* HPH_R */
|
||||
COMPANDER_3, /* LO1_DIFF */
|
||||
COMPANDER_4, /* LO2_DIFF */
|
||||
COMPANDER_5, /* LO3_SE */
|
||||
COMPANDER_6, /* LO4_SE */
|
||||
COMPANDER_7, /* SWR SPK CH1 */
|
||||
COMPANDER_8, /* SWR SPK CH2 */
|
||||
COMPANDER_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
INTn_2_INP_SEL_ZERO = 0,
|
||||
INTn_2_INP_SEL_RX0,
|
||||
@ -184,6 +196,8 @@ struct wcd9335_codec {
|
||||
|
||||
struct wcd_clsh_ctrl *clsh_ctrl;
|
||||
u32 hph_mode;
|
||||
int comp_enabled[COMPANDER_MAX];
|
||||
|
||||
int intr1;
|
||||
int reset_gpio;
|
||||
struct regulator_bulk_data supplies[WCD9335_MAX_SUPPLY];
|
||||
@ -301,6 +315,111 @@ static const struct wcd9335_reg_mask_val wcd9335_codec_reg_init[] = {
|
||||
{WCD9335_HPH_REFBUFF_LP_CTL, 0x06, 0x02},
|
||||
};
|
||||
|
||||
/* Cutoff frequency for high pass filter */
|
||||
static const char * const cf_text[] = {
|
||||
"CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
|
||||
};
|
||||
|
||||
static const char * const rx_cf_text[] = {
|
||||
"CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ",
|
||||
"CF_NEG_3DB_0P48HZ"
|
||||
};
|
||||
|
||||
static const char * const rx_hph_mode_mux_text[] = {
|
||||
"Class H Invalid", "Class-H Hi-Fi", "Class-H Low Power", "Class-AB",
|
||||
"Class-H Hi-Fi Low Power"
|
||||
};
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
|
||||
static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
|
||||
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
|
||||
static const DECLARE_TLV_DB_SCALE(ear_pa_gain, 0, 150, 0);
|
||||
|
||||
static const struct soc_enum cf_dec0_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_TX0_TX_PATH_CFG0, 5, 3, cf_text);
|
||||
|
||||
static const struct soc_enum cf_dec1_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_TX1_TX_PATH_CFG0, 5, 3, cf_text);
|
||||
|
||||
static const struct soc_enum cf_dec2_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_TX2_TX_PATH_CFG0, 5, 3, cf_text);
|
||||
|
||||
static const struct soc_enum cf_dec3_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_TX3_TX_PATH_CFG0, 5, 3, cf_text);
|
||||
|
||||
static const struct soc_enum cf_dec4_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_TX4_TX_PATH_CFG0, 5, 3, cf_text);
|
||||
|
||||
static const struct soc_enum cf_dec5_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_TX5_TX_PATH_CFG0, 5, 3, cf_text);
|
||||
|
||||
static const struct soc_enum cf_dec6_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_TX6_TX_PATH_CFG0, 5, 3, cf_text);
|
||||
|
||||
static const struct soc_enum cf_dec7_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_TX7_TX_PATH_CFG0, 5, 3, cf_text);
|
||||
|
||||
static const struct soc_enum cf_dec8_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_TX8_TX_PATH_CFG0, 5, 3, cf_text);
|
||||
|
||||
static const struct soc_enum cf_int0_1_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_RX0_RX_PATH_CFG2, 0, 4, rx_cf_text);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(cf_int0_2_enum, WCD9335_CDC_RX0_RX_PATH_MIX_CFG, 2,
|
||||
rx_cf_text);
|
||||
|
||||
static const struct soc_enum cf_int1_1_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_RX1_RX_PATH_CFG2, 0, 4, rx_cf_text);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(cf_int1_2_enum, WCD9335_CDC_RX1_RX_PATH_MIX_CFG, 2,
|
||||
rx_cf_text);
|
||||
|
||||
static const struct soc_enum cf_int2_1_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_RX2_RX_PATH_CFG2, 0, 4, rx_cf_text);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(cf_int2_2_enum, WCD9335_CDC_RX2_RX_PATH_MIX_CFG, 2,
|
||||
rx_cf_text);
|
||||
|
||||
static const struct soc_enum cf_int3_1_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_RX3_RX_PATH_CFG2, 0, 4, rx_cf_text);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(cf_int3_2_enum, WCD9335_CDC_RX3_RX_PATH_MIX_CFG, 2,
|
||||
rx_cf_text);
|
||||
|
||||
static const struct soc_enum cf_int4_1_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_RX4_RX_PATH_CFG2, 0, 4, rx_cf_text);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(cf_int4_2_enum, WCD9335_CDC_RX4_RX_PATH_MIX_CFG, 2,
|
||||
rx_cf_text);
|
||||
|
||||
static const struct soc_enum cf_int5_1_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_RX5_RX_PATH_CFG2, 0, 4, rx_cf_text);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(cf_int5_2_enum, WCD9335_CDC_RX5_RX_PATH_MIX_CFG, 2,
|
||||
rx_cf_text);
|
||||
|
||||
static const struct soc_enum cf_int6_1_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_RX6_RX_PATH_CFG2, 0, 4, rx_cf_text);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(cf_int6_2_enum, WCD9335_CDC_RX6_RX_PATH_MIX_CFG, 2,
|
||||
rx_cf_text);
|
||||
|
||||
static const struct soc_enum cf_int7_1_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_RX7_RX_PATH_CFG2, 0, 4, rx_cf_text);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(cf_int7_2_enum, WCD9335_CDC_RX7_RX_PATH_MIX_CFG, 2,
|
||||
rx_cf_text);
|
||||
|
||||
static const struct soc_enum cf_int8_1_enum =
|
||||
SOC_ENUM_SINGLE(WCD9335_CDC_RX8_RX_PATH_CFG2, 0, 4, rx_cf_text);
|
||||
|
||||
static SOC_ENUM_SINGLE_DECL(cf_int8_2_enum, WCD9335_CDC_RX8_RX_PATH_MIX_CFG, 2,
|
||||
rx_cf_text);
|
||||
|
||||
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 int wcd9335_set_mix_interpolator_rate(struct snd_soc_dai *dai,
|
||||
int rate_val,
|
||||
u32 rate)
|
||||
@ -697,6 +816,210 @@ static struct snd_soc_dai_driver wcd9335_slim_dais[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int wcd9335_get_compander(struct snd_kcontrol *kc,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kc);
|
||||
int comp = ((struct soc_mixer_control *)kc->private_value)->shift;
|
||||
struct wcd9335_codec *wcd = dev_get_drvdata(component->dev);
|
||||
|
||||
ucontrol->value.integer.value[0] = wcd->comp_enabled[comp];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd9335_set_compander(struct snd_kcontrol *kc,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kc);
|
||||
struct wcd9335_codec *wcd = dev_get_drvdata(component->dev);
|
||||
int comp = ((struct soc_mixer_control *) kc->private_value)->shift;
|
||||
int value = ucontrol->value.integer.value[0];
|
||||
int sel;
|
||||
|
||||
wcd->comp_enabled[comp] = value;
|
||||
sel = value ? WCD9335_HPH_GAIN_SRC_SEL_COMPANDER :
|
||||
WCD9335_HPH_GAIN_SRC_SEL_REGISTER;
|
||||
|
||||
/* Any specific register configuration for compander */
|
||||
switch (comp) {
|
||||
case COMPANDER_1:
|
||||
/* Set Gain Source Select based on compander enable/disable */
|
||||
snd_soc_component_update_bits(component, WCD9335_HPH_L_EN,
|
||||
WCD9335_HPH_GAIN_SRC_SEL_MASK, sel);
|
||||
break;
|
||||
case COMPANDER_2:
|
||||
snd_soc_component_update_bits(component, WCD9335_HPH_R_EN,
|
||||
WCD9335_HPH_GAIN_SRC_SEL_MASK, sel);
|
||||
break;
|
||||
case COMPANDER_5:
|
||||
snd_soc_component_update_bits(component, WCD9335_SE_LO_LO3_GAIN,
|
||||
WCD9335_HPH_GAIN_SRC_SEL_MASK, sel);
|
||||
break;
|
||||
case COMPANDER_6:
|
||||
snd_soc_component_update_bits(component, WCD9335_SE_LO_LO4_GAIN,
|
||||
WCD9335_HPH_GAIN_SRC_SEL_MASK, sel);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd9335_rx_hph_mode_get(struct snd_kcontrol *kc,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kc);
|
||||
struct wcd9335_codec *wcd = dev_get_drvdata(component->dev);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = wcd->hph_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wcd9335_rx_hph_mode_put(struct snd_kcontrol *kc,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kc);
|
||||
struct wcd9335_codec *wcd = dev_get_drvdata(component->dev);
|
||||
u32 mode_val;
|
||||
|
||||
mode_val = ucontrol->value.enumerated.item[0];
|
||||
|
||||
if (mode_val == 0) {
|
||||
dev_err(wcd->dev, "Invalid HPH Mode, default to ClSH HiFi\n");
|
||||
mode_val = CLS_H_HIFI;
|
||||
}
|
||||
wcd->hph_mode = mode_val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new wcd9335_snd_controls[] = {
|
||||
/* -84dB min - 40dB max */
|
||||
SOC_SINGLE_SX_TLV("RX0 Digital Volume", WCD9335_CDC_RX0_RX_VOL_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX1 Digital Volume", WCD9335_CDC_RX1_RX_VOL_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX2 Digital Volume", WCD9335_CDC_RX2_RX_VOL_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX3 Digital Volume", WCD9335_CDC_RX3_RX_VOL_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX4 Digital Volume", WCD9335_CDC_RX4_RX_VOL_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX5 Digital Volume", WCD9335_CDC_RX5_RX_VOL_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX6 Digital Volume", WCD9335_CDC_RX6_RX_VOL_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX7 Digital Volume", WCD9335_CDC_RX7_RX_VOL_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX8 Digital Volume", WCD9335_CDC_RX8_RX_VOL_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX0 Mix Digital Volume",
|
||||
WCD9335_CDC_RX0_RX_VOL_MIX_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX1 Mix Digital Volume",
|
||||
WCD9335_CDC_RX1_RX_VOL_MIX_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX2 Mix Digital Volume",
|
||||
WCD9335_CDC_RX2_RX_VOL_MIX_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX3 Mix Digital Volume",
|
||||
WCD9335_CDC_RX3_RX_VOL_MIX_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX4 Mix Digital Volume",
|
||||
WCD9335_CDC_RX4_RX_VOL_MIX_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX5 Mix Digital Volume",
|
||||
WCD9335_CDC_RX5_RX_VOL_MIX_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX6 Mix Digital Volume",
|
||||
WCD9335_CDC_RX6_RX_VOL_MIX_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX7 Mix Digital Volume",
|
||||
WCD9335_CDC_RX7_RX_VOL_MIX_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_SINGLE_SX_TLV("RX8 Mix Digital Volume",
|
||||
WCD9335_CDC_RX8_RX_VOL_MIX_CTL,
|
||||
0, -84, 40, digital_gain),
|
||||
SOC_ENUM("RX INT0_1 HPF cut off", cf_int0_1_enum),
|
||||
SOC_ENUM("RX INT0_2 HPF cut off", cf_int0_2_enum),
|
||||
SOC_ENUM("RX INT1_1 HPF cut off", cf_int1_1_enum),
|
||||
SOC_ENUM("RX INT1_2 HPF cut off", cf_int1_2_enum),
|
||||
SOC_ENUM("RX INT2_1 HPF cut off", cf_int2_1_enum),
|
||||
SOC_ENUM("RX INT2_2 HPF cut off", cf_int2_2_enum),
|
||||
SOC_ENUM("RX INT3_1 HPF cut off", cf_int3_1_enum),
|
||||
SOC_ENUM("RX INT3_2 HPF cut off", cf_int3_2_enum),
|
||||
SOC_ENUM("RX INT4_1 HPF cut off", cf_int4_1_enum),
|
||||
SOC_ENUM("RX INT4_2 HPF cut off", cf_int4_2_enum),
|
||||
SOC_ENUM("RX INT5_1 HPF cut off", cf_int5_1_enum),
|
||||
SOC_ENUM("RX INT5_2 HPF cut off", cf_int5_2_enum),
|
||||
SOC_ENUM("RX INT6_1 HPF cut off", cf_int6_1_enum),
|
||||
SOC_ENUM("RX INT6_2 HPF cut off", cf_int6_2_enum),
|
||||
SOC_ENUM("RX INT7_1 HPF cut off", cf_int7_1_enum),
|
||||
SOC_ENUM("RX INT7_2 HPF cut off", cf_int7_2_enum),
|
||||
SOC_ENUM("RX INT8_1 HPF cut off", cf_int8_1_enum),
|
||||
SOC_ENUM("RX INT8_2 HPF cut off", cf_int8_2_enum),
|
||||
SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
|
||||
wcd9335_get_compander, wcd9335_set_compander),
|
||||
SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
|
||||
wcd9335_get_compander, wcd9335_set_compander),
|
||||
SOC_SINGLE_EXT("COMP3 Switch", SND_SOC_NOPM, COMPANDER_3, 1, 0,
|
||||
wcd9335_get_compander, wcd9335_set_compander),
|
||||
SOC_SINGLE_EXT("COMP4 Switch", SND_SOC_NOPM, COMPANDER_4, 1, 0,
|
||||
wcd9335_get_compander, wcd9335_set_compander),
|
||||
SOC_SINGLE_EXT("COMP5 Switch", SND_SOC_NOPM, COMPANDER_5, 1, 0,
|
||||
wcd9335_get_compander, wcd9335_set_compander),
|
||||
SOC_SINGLE_EXT("COMP6 Switch", SND_SOC_NOPM, COMPANDER_6, 1, 0,
|
||||
wcd9335_get_compander, wcd9335_set_compander),
|
||||
SOC_SINGLE_EXT("COMP7 Switch", SND_SOC_NOPM, COMPANDER_7, 1, 0,
|
||||
wcd9335_get_compander, wcd9335_set_compander),
|
||||
SOC_SINGLE_EXT("COMP8 Switch", SND_SOC_NOPM, COMPANDER_8, 1, 0,
|
||||
wcd9335_get_compander, wcd9335_set_compander),
|
||||
SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,
|
||||
wcd9335_rx_hph_mode_get, wcd9335_rx_hph_mode_put),
|
||||
|
||||
/* Gain Controls */
|
||||
SOC_SINGLE_TLV("EAR PA Volume", WCD9335_ANA_EAR, 4, 4, 1,
|
||||
ear_pa_gain),
|
||||
SOC_SINGLE_TLV("HPHL Volume", WCD9335_HPH_L_EN, 0, 20, 1,
|
||||
line_gain),
|
||||
SOC_SINGLE_TLV("HPHR Volume", WCD9335_HPH_R_EN, 0, 20, 1,
|
||||
line_gain),
|
||||
SOC_SINGLE_TLV("LINEOUT1 Volume", WCD9335_DIFF_LO_LO1_COMPANDER,
|
||||
3, 16, 1, line_gain),
|
||||
SOC_SINGLE_TLV("LINEOUT2 Volume", WCD9335_DIFF_LO_LO2_COMPANDER,
|
||||
3, 16, 1, line_gain),
|
||||
SOC_SINGLE_TLV("LINEOUT3 Volume", WCD9335_SE_LO_LO3_GAIN, 0, 20, 1,
|
||||
line_gain),
|
||||
SOC_SINGLE_TLV("LINEOUT4 Volume", WCD9335_SE_LO_LO4_GAIN, 0, 20, 1,
|
||||
line_gain),
|
||||
|
||||
SOC_SINGLE_TLV("ADC1 Volume", WCD9335_ANA_AMIC1, 0, 20, 0,
|
||||
analog_gain),
|
||||
SOC_SINGLE_TLV("ADC2 Volume", WCD9335_ANA_AMIC2, 0, 20, 0,
|
||||
analog_gain),
|
||||
SOC_SINGLE_TLV("ADC3 Volume", WCD9335_ANA_AMIC3, 0, 20, 0,
|
||||
analog_gain),
|
||||
SOC_SINGLE_TLV("ADC4 Volume", WCD9335_ANA_AMIC4, 0, 20, 0,
|
||||
analog_gain),
|
||||
SOC_SINGLE_TLV("ADC5 Volume", WCD9335_ANA_AMIC5, 0, 20, 0,
|
||||
analog_gain),
|
||||
SOC_SINGLE_TLV("ADC6 Volume", WCD9335_ANA_AMIC6, 0, 20, 0,
|
||||
analog_gain),
|
||||
|
||||
SOC_ENUM("TX0 HPF cut off", cf_dec0_enum),
|
||||
SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
|
||||
SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
|
||||
SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
|
||||
SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
|
||||
SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
|
||||
SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
|
||||
SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
|
||||
SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
|
||||
};
|
||||
|
||||
static irqreturn_t wcd9335_slimbus_irq(int irq, void *data)
|
||||
{
|
||||
struct wcd9335_codec *wcd = data;
|
||||
@ -1162,6 +1485,8 @@ static const struct snd_soc_component_driver wcd9335_component_drv = {
|
||||
.probe = wcd9335_codec_probe,
|
||||
.remove = wcd9335_codec_remove,
|
||||
.set_sysclk = wcd9335_codec_set_sysclk,
|
||||
.controls = wcd9335_snd_controls,
|
||||
.num_controls = ARRAY_SIZE(wcd9335_snd_controls),
|
||||
};
|
||||
|
||||
static int wcd9335_probe(struct wcd9335_codec *wcd)
|
||||
|
Loading…
Reference in New Issue
Block a user