summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorXing Zheng <zhengxing@rock-chips.com>2019-01-30 10:07:56 +0800
committerTao Huang <huangtao@rock-chips.com>2019-02-01 11:51:21 +0800
commit9c163ef822efe929f4c9837dd32384f949fce840 (patch)
tree01c48d1ee3bc5fcddca83a4185e94efa66f05301 /sound
parentfdff04d652f0df833b1487ef11ed95653b1868c6 (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.c80
-rw-r--r--sound/soc/codecs/rk3308_codec.h5
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)