diff options
author | Kevin Lu <luminlong@139.com> | 2022-08-15 14:27:15 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2022-08-17 15:00:29 +0300 |
commit | 4e82971f7b556cff3491c867e8840e7d788693b9 (patch) | |
tree | 448bbc2eb23614c159b9301f3ea96ae50c4901d8 /sound/soc/codecs/tlv320adcx140.c | |
parent | ea15d3bd3cd6e9483bb8aa664954c0a8cde253eb (diff) | |
download | linux-4e82971f7b556cff3491c867e8840e7d788693b9.tar.xz |
ASoC: tlv320adcx140: Add a new kcontrol
Add a new kcontrol for phase calib
Signed-off-by: Kevin Lu <luminlong@139.com>
Link: https://lore.kernel.org/r/20220815112715.21617-1-luminlong@139.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/codecs/tlv320adcx140.c')
-rw-r--r-- | sound/soc/codecs/tlv320adcx140.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c index 2844a9d2bc4a..91a22d927915 100644 --- a/sound/soc/codecs/tlv320adcx140.c +++ b/sound/soc/codecs/tlv320adcx140.c @@ -31,6 +31,7 @@ struct adcx140_priv { struct device *dev; bool micbias_vg; + bool phase_calib_on; unsigned int dai_fmt; unsigned int slot_width; @@ -592,6 +593,52 @@ static const struct snd_soc_dapm_route adcx140_audio_map[] = { {"MIC4M Input Mux", "Digital", "MIC4M"}, }; +#define ADCX140_PHASE_CALIB_SWITCH(xname) {\ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .info = adcx140_phase_calib_info, \ + .get = adcx140_phase_calib_get, \ + .put = adcx140_phase_calib_put} + +static int adcx140_phase_calib_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int adcx140_phase_calib_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *value) +{ + struct snd_soc_component *codec = + snd_soc_kcontrol_component(kcontrol); + struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(codec); + + value->value.integer.value[0] = adcx140->phase_calib_on ? 1 : 0; + + + return 0; +} + +static int adcx140_phase_calib_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *value) +{ + struct snd_soc_component *codec + = snd_soc_kcontrol_component(kcontrol); + struct adcx140_priv *adcx140 = snd_soc_component_get_drvdata(codec); + + bool v = value->value.integer.value[0] ? true : false; + + if (adcx140->phase_calib_on != v) { + adcx140->phase_calib_on = v; + return 1; + } + return 0; +} + static const struct snd_kcontrol_new adcx140_snd_controls[] = { SOC_SINGLE_TLV("Analog CH1 Mic Gain Volume", ADCX140_CH1_CFG1, 2, 42, 0, adc_tlv), @@ -628,6 +675,7 @@ static const struct snd_kcontrol_new adcx140_snd_controls[] = { 0, 0xff, 0, dig_vol_tlv), SOC_SINGLE_TLV("Digital CH8 Out Volume", ADCX140_CH8_CFG2, 0, 0xff, 0, dig_vol_tlv), + ADCX140_PHASE_CALIB_SWITCH("Phase Calibration Switch"), }; static int adcx140_reset(struct adcx140_priv *adcx140) @@ -653,6 +701,8 @@ static int adcx140_reset(struct adcx140_priv *adcx140) static void adcx140_pwr_ctrl(struct adcx140_priv *adcx140, bool power_state) { int pwr_ctrl = 0; + int ret = 0; + struct snd_soc_component *component = adcx140->component; if (power_state) pwr_ctrl = ADCX140_PWR_CFG_ADC_PDZ | ADCX140_PWR_CFG_PLL_PDZ; @@ -660,6 +710,14 @@ static void adcx140_pwr_ctrl(struct adcx140_priv *adcx140, bool power_state) if (adcx140->micbias_vg && power_state) pwr_ctrl |= ADCX140_PWR_CFG_BIAS_PDZ; + if (pwr_ctrl) { + ret = regmap_write(adcx140->regmap, ADCX140_PHASE_CALIB, + adcx140->phase_calib_on ? 0x00 : 0x40); + if (ret) + dev_err(component->dev, "%s: register write error %d\n", + __func__, ret); + } + regmap_update_bits(adcx140->regmap, ADCX140_PWR_CFG, ADCX140_PWR_CTRL_MSK, pwr_ctrl); } @@ -1095,6 +1153,7 @@ static int adcx140_i2c_probe(struct i2c_client *i2c) if (!adcx140) return -ENOMEM; + adcx140->phase_calib_on = false; adcx140->dev = &i2c->dev; adcx140->gpio_reset = devm_gpiod_get_optional(adcx140->dev, |