diff options
author | Xing Zheng <zhengxing@rock-chips.com> | 2019-01-30 10:07:56 +0800 |
---|---|---|
committer | Tao Huang <huangtao@rock-chips.com> | 2019-02-01 11:51:21 +0800 |
commit | 9c163ef822efe929f4c9837dd32384f949fce840 (patch) | |
tree | 01c48d1ee3bc5fcddca83a4185e94efa66f05301 /sound | |
parent | fdff04d652f0df833b1487ef11ed95653b1868c6 (diff) |
ASoC: rk3308_codec: Add the range of MICBIAS voltages
Change-Id: Ie9d1d4fc8854cc4111cbb1a324525f849c5c470a
Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/rk3308_codec.c | 80 | ||||
-rw-r--r-- | sound/soc/codecs/rk3308_codec.h | 5 |
2 files changed, 82 insertions, 3 deletions
diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c index e8e67bbf3320..48a63a670514 100644 --- a/sound/soc/codecs/rk3308_codec.c +++ b/sound/soc/codecs/rk3308_codec.c @@ -171,6 +171,7 @@ struct rk3308_codec_priv { u32 delay_start_play_ms; u32 delay_pa_drv_ms; u32 micbias_num; + u32 micbias_volt; int which_i2s; int irq; int adc_grp0_using_linein; @@ -245,6 +246,8 @@ static const DECLARE_TLV_DB_RANGE(rk3308_codec_adc_mic_gain_tlv_b, static bool handle_loopback(struct rk3308_codec_priv *rk3308); +static int check_micbias(int micbias); + static int rk3308_codec_micbias_enable(struct rk3308_codec_priv *rk3308, int micbias); static int rk3308_codec_micbias_disable(struct rk3308_codec_priv *rk3308); @@ -277,6 +280,10 @@ static int rk3308_codec_mic_gain_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); static int rk3308_codec_mic_gain_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +static int rk3308_codec_micbias_volts_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +static int rk3308_codec_micbias_volts_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); static int rk3308_codec_main_micbias_put(struct snd_kcontrol *kcontrol, @@ -292,6 +299,33 @@ static const char *mute_text[2] = { [1] = "Mute", }; +/* ADC MICBIAS Volt */ +#define MICBIAS_VOLT_NUM 8 + +#define MICBIAS_VREFx0_5 0 +#define MICBIAS_VREFx0_55 1 +#define MICBIAS_VREFx0_6 2 +#define MICBIAS_VREFx0_65 3 +#define MICBIAS_VREFx0_7 4 +#define MICBIAS_VREFx0_75 5 +#define MICBIAS_VREFx0_8 6 +#define MICBIAS_VREFx0_85 7 + +static const char *micbias_volts_enum_array[MICBIAS_VOLT_NUM] = { + [MICBIAS_VREFx0_5] = "VREFx0_5", + [MICBIAS_VREFx0_55] = "VREFx0_55", + [MICBIAS_VREFx0_6] = "VREFx0_6", + [MICBIAS_VREFx0_65] = "VREFx0_65", + [MICBIAS_VREFx0_7] = "VREFx0_7", + [MICBIAS_VREFx0_75] = "VREFx0_75", + [MICBIAS_VREFx0_8] = "VREFx0_8", + [MICBIAS_VREFx0_85] = "VREFx0_85", +}; + +static const struct soc_enum rk3308_micbias_volts_enum_array[] = { + SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(micbias_volts_enum_array), micbias_volts_enum_array), +}; + /* ADC MICBIAS1 and MICBIAS2 Main Switch */ static const struct soc_enum rk3308_main_micbias_enum_array[] = { SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text), @@ -694,6 +728,10 @@ 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 MICBIAS Voltage */ + SOC_ENUM_EXT("ADC MICBIAS Voltage", rk3308_micbias_volts_enum_array[0], + rk3308_codec_micbias_volts_get, rk3308_codec_micbias_volts_put), + /* ADC Main MICBIAS Switch */ SOC_ENUM_EXT("ADC Main MICBIAS", rk3308_main_micbias_enum_array[0], rk3308_codec_main_micbias_get, rk3308_codec_main_micbias_put), @@ -1042,6 +1080,41 @@ static int rk3308_codec_mic_mute_put(struct snd_kcontrol *kcontrol, return 0; } +static int rk3308_codec_micbias_volts_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); + + ucontrol->value.integer.value[0] = rk3308->micbias_volt; + + return 0; +} + +static int rk3308_codec_micbias_volts_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); + unsigned int volt = ucontrol->value.integer.value[0]; + int ret; + + ret = check_micbias(volt); + if (ret < 0) { + dev_err(rk3308->plat_dev, "The invalid micbias volt: %d\n", + volt); + return ret; + } + + regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), + RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, + volt); + + rk3308->micbias_volt = volt; + + return 0; +} + static int rk3308_codec_main_micbias_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1062,7 +1135,7 @@ static int rk3308_codec_main_micbias_put(struct snd_kcontrol *kcontrol, if (on) { if (!rk3308->enable_micbias) - rk3308_codec_micbias_enable(rk3308, RK3308_ADC_MICBIAS_VOLT_0_85); + rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt); } else { if (rk3308->enable_micbias) rk3308_codec_micbias_disable(rk3308); @@ -3403,7 +3476,7 @@ static int rk3308_codec_dlp_down(struct rk3308_codec_priv *rk3308) static int rk3308_codec_dlp_up(struct rk3308_codec_priv *rk3308) { rk3308_codec_power_on(rk3308); - rk3308_codec_micbias_enable(rk3308, RK3308_ADC_MICBIAS_VOLT_0_85); + rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt); return 0; } @@ -3506,7 +3579,7 @@ static int rk3308_hw_params(struct snd_pcm_substream *substream, } else { if (rk3308->micbias_num && !rk3308->enable_micbias) - rk3308_codec_micbias_enable(rk3308, RK3308_ADC_MICBIAS_VOLT_0_85); + rk3308_codec_micbias_enable(rk3308, rk3308->micbias_volt); rk3308_codec_adc_mclk_enable(rk3308); ret = rk3308_codec_update_adc_grps(rk3308, params); @@ -3870,6 +3943,7 @@ static int rk3308_codec_check_micbias(struct rk3308_codec_priv *rk3308, if (rk3308->micbias2) num++; + rk3308->micbias_volt = RK3308_ADC_MICBIAS_VOLT_0_85; /* by default */ rk3308->micbias_num = num; return 0; diff --git a/sound/soc/codecs/rk3308_codec.h b/sound/soc/codecs/rk3308_codec.h index 1ac874251641..93e089dae081 100644 --- a/sound/soc/codecs/rk3308_codec.h +++ b/sound/soc/codecs/rk3308_codec.h @@ -798,6 +798,11 @@ #define RK3308_ADC_MIC_BIAS_BUF_DIS (0x0 << RK3308_ADC_MIC_BIAS_BUF_SFT) #define RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT 0 #define RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) +/* + * The follow MICBIAS_VOLTs are based on the external reference voltage(Vref). + * For example, the Vref == 3.3V, the MICBIAS_VOLT_0_85 is equal: + * 3.3V * 0.85 = 2.805V. + */ #define RK3308_ADC_MICBIAS_VOLT_0_85 (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) #define RK3308_ADC_MICBIAS_VOLT_0_8 (0x6 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) #define RK3308_ADC_MICBIAS_VOLT_0_75 (0x5 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) |