ASoC: rk3308_codec: add supports Mute/Work switches for ADC MICs

Change-Id: If8714a3182cded36bfc1d36d1d29493f2e51cccf
Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
This commit is contained in:
Xing Zheng
2018-09-27 11:46:20 +08:00
committed by Tao Huang
parent 6e708ed708
commit 2baef6b134

View File

@@ -169,6 +169,10 @@ struct rk3308_codec_priv {
unsigned int agc_asr_l[ADC_LR_GROUP_MAX];
unsigned int agc_asr_r[ADC_LR_GROUP_MAX];
/* ADC MIC Mute/Work */
unsigned int mic_mute_l[ADC_LR_GROUP_MAX];
unsigned int mic_mute_r[ADC_LR_GROUP_MAX];
/* For the high pass filter */
unsigned int hpf_cutoff[ADC_LR_GROUP_MAX];
@@ -236,12 +240,21 @@ static int rk3308_codec_agc_asr_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
static int rk3308_codec_agc_asr_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
static const char *offon_text[2] = {
[0] = "Off",
[1] = "On",
};
static const char *mute_text[2] = {
[0] = "Work",
[1] = "Mute",
};
#define HPF_NUM 4
#define HPF_CUTOFF_20HZ 0
@@ -275,6 +288,18 @@ static const struct soc_enum rk3308_agc_enum_array[] = {
SOC_ENUM_SINGLE(3, 1, ARRAY_SIZE(offon_text), offon_text),
};
/* ADC MIC Mute/Work Switch */
static const struct soc_enum rk3308_mic_mute_enum_array[] = {
SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(mute_text), mute_text),
SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(mute_text), mute_text),
SOC_ENUM_SINGLE(1, 0, ARRAY_SIZE(mute_text), mute_text),
SOC_ENUM_SINGLE(1, 1, ARRAY_SIZE(mute_text), mute_text),
SOC_ENUM_SINGLE(2, 0, ARRAY_SIZE(mute_text), mute_text),
SOC_ENUM_SINGLE(2, 1, ARRAY_SIZE(mute_text), mute_text),
SOC_ENUM_SINGLE(3, 0, ARRAY_SIZE(mute_text), mute_text),
SOC_ENUM_SINGLE(3, 1, ARRAY_SIZE(mute_text), mute_text),
};
/* ALC AGC Approximate Sample Rate */
#define AGC_ASR_NUM 8
@@ -505,6 +530,24 @@ static const struct snd_kcontrol_new rk3308_codec_dapm_controls[] = {
SOC_ENUM_EXT("AGC Group 3 Right Approximate Sample Rate", rk3308_agc_asr_enum_array[7],
rk3308_codec_agc_asr_get, rk3308_codec_agc_asr_put),
/* ADC MIC Mute/Work Switch */
SOC_ENUM_EXT("ADC MIC Group 0 Left Switch", rk3308_mic_mute_enum_array[0],
rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
SOC_ENUM_EXT("ADC MIC Group 0 Right Switch", rk3308_mic_mute_enum_array[1],
rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
SOC_ENUM_EXT("ADC MIC Group 1 Left Switch", rk3308_mic_mute_enum_array[2],
rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
SOC_ENUM_EXT("ADC MIC Group 1 Right Switch", rk3308_mic_mute_enum_array[3],
rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
SOC_ENUM_EXT("ADC MIC Group 2 Left Switch", rk3308_mic_mute_enum_array[4],
rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
SOC_ENUM_EXT("ADC MIC Group 2 Right Switch", rk3308_mic_mute_enum_array[5],
rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
SOC_ENUM_EXT("ADC MIC Group 3 Left Switch", rk3308_mic_mute_enum_array[6],
rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
SOC_ENUM_EXT("ADC MIC Group 3 Right Switch", rk3308_mic_mute_enum_array[7],
rk3308_codec_mic_mute_get, rk3308_codec_mic_mute_put),
/* ADC MIC */
SOC_SINGLE_RANGE_TLV("ADC MIC Group 0 Left Volume",
RK3308_ADC_ANA_CON01(0),
@@ -809,6 +852,72 @@ static int rk3308_codec_agc_asr_put(struct snd_kcontrol *kcontrol,
return 0;
}
static int rk3308_codec_mic_mute_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int value;
int grp = e->reg;
if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) {
dev_err(rk3308->plat_dev,
"%s: Invalid ADC grp: %d\n", __func__, e->reg);
return -EINVAL;
}
if (e->shift_l) {
/* ADC MIC Right Mute/Work Infos */
regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), &value);
rk3308->mic_mute_r[e->reg] = (value & RK3308_ADC_R_CH_BIST_SINE) >>
RK3308_ADC_R_CH_BIST_SFT;
ucontrol->value.integer.value[0] = rk3308->mic_mute_r[e->reg];
} else {
/* ADC MIC Left Mute/Work Infos */
regmap_read(rk3308->regmap, RK3308_ADC_DIG_CON03(grp), &value);
rk3308->mic_mute_l[e->reg] = (value & RK3308_ADC_L_CH_BIST_SINE) >>
RK3308_ADC_L_CH_BIST_SFT;
ucontrol->value.integer.value[0] = rk3308->mic_mute_l[e->reg];
}
return 0;
}
static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
struct rk3308_codec_priv *rk3308 = snd_soc_codec_get_drvdata(codec);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int value;
int grp = e->reg;
if (e->reg < 0 || e->reg > ADC_LR_GROUP_MAX - 1) {
dev_err(rk3308->plat_dev,
"%s: Invalid ADC grp: %d\n", __func__, e->reg);
return -EINVAL;
}
if (e->shift_l) {
/* ADC MIC Right Mute/Work Configuration */
value = ucontrol->value.integer.value[0] << RK3308_ADC_R_CH_BIST_SFT;
regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(grp),
RK3308_ADC_R_CH_BIST_SINE,
value);
rk3308->mic_mute_r[e->reg] = ucontrol->value.integer.value[0];
} else {
/* ADC MIC Left Mute/Work Configuration */
value = ucontrol->value.integer.value[0] << RK3308_ADC_L_CH_BIST_SFT;
regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON03(grp),
RK3308_ADC_L_CH_BIST_SINE,
value);
rk3308->mic_mute_l[e->reg] = ucontrol->value.integer.value[0];
}
return 0;
}
static int rk3308_codec_hpf_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{