Commit 9d4befff authored by Michael Sit Wei Hong's avatar Michael Sit Wei Hong Committed by Mark Brown

ASoC: codec: tlv3204: Moving GPIO reset and add ADC reset

Moving GPIO reset to a later stage and before clock registration to
ensure that the host system and codec clocks are in sync. If the host
register clock values prior to gpio reset, the last configured codec clock
is registered to the host. The codec then gets gpio resetted setting the
codec clocks to their default value, causing a mismatch. Host system will
skip clock setting thinking the codec clocks are already at the requested
rate.

ADC reset is added to ensure the next audio capture does not have
undesired artifacts. It is probably related to the original code
where the probe function resets the ADC prior to 1st record.
Signed-off-by: default avatarMichael Sit Wei Hong <michael.wei.hong.sit@intel.com>
Reviewed-by: default avatarSia Jee Heng <jee.heng.sia@intel.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20200812094631.4698-4-michael.wei.hong.sit@intel.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent d1c859d3
...@@ -50,6 +50,28 @@ struct aic32x4_priv { ...@@ -50,6 +50,28 @@ struct aic32x4_priv {
struct device *dev; struct device *dev;
}; };
static int aic32x4_reset_adc(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
u32 adc_reg;
/*
* Workaround: the datasheet does not mention a required programming
* sequence but experiments show the ADC needs to be reset after each
* capture to avoid audible artifacts.
*/
switch (event) {
case SND_SOC_DAPM_POST_PMD:
adc_reg = snd_soc_component_read(component, AIC32X4_ADCSETUP);
snd_soc_component_write(component, AIC32X4_ADCSETUP, adc_reg |
AIC32X4_LADC_EN | AIC32X4_RADC_EN);
snd_soc_component_write(component, AIC32X4_ADCSETUP, adc_reg);
break;
}
return 0;
};
static int mic_bias_event(struct snd_soc_dapm_widget *w, static int mic_bias_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event) struct snd_kcontrol *kcontrol, int event)
{ {
...@@ -434,6 +456,7 @@ static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = { ...@@ -434,6 +456,7 @@ static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("Mic Bias", AIC32X4_MICBIAS, 6, 0, mic_bias_event, SND_SOC_DAPM_SUPPLY("Mic Bias", AIC32X4_MICBIAS, 6, 0, mic_bias_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_POST("ADC Reset", aic32x4_reset_adc),
SND_SOC_DAPM_OUTPUT("HPL"), SND_SOC_DAPM_OUTPUT("HPL"),
SND_SOC_DAPM_OUTPUT("HPR"), SND_SOC_DAPM_OUTPUT("HPR"),
...@@ -958,12 +981,6 @@ static int aic32x4_component_probe(struct snd_soc_component *component) ...@@ -958,12 +981,6 @@ static int aic32x4_component_probe(struct snd_soc_component *component)
if (ret) if (ret)
return ret; return ret;
if (gpio_is_valid(aic32x4->rstn_gpio)) {
ndelay(10);
gpio_set_value(aic32x4->rstn_gpio, 1);
mdelay(1);
}
snd_soc_component_write(component, AIC32X4_RESET, 0x01); snd_soc_component_write(component, AIC32X4_RESET, 0x01);
if (aic32x4->setup) if (aic32x4->setup)
...@@ -1196,10 +1213,6 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap) ...@@ -1196,10 +1213,6 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap)
aic32x4->mclk_name = "mclk"; aic32x4->mclk_name = "mclk";
} }
ret = aic32x4_register_clocks(dev, aic32x4->mclk_name);
if (ret)
return ret;
if (gpio_is_valid(aic32x4->rstn_gpio)) { if (gpio_is_valid(aic32x4->rstn_gpio)) {
ret = devm_gpio_request_one(dev, aic32x4->rstn_gpio, ret = devm_gpio_request_one(dev, aic32x4->rstn_gpio,
GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
...@@ -1221,6 +1234,16 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap) ...@@ -1221,6 +1234,16 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap)
return ret; return ret;
} }
if (gpio_is_valid(aic32x4->rstn_gpio)) {
ndelay(10);
gpio_set_value_cansleep(aic32x4->rstn_gpio, 1);
mdelay(1);
}
ret = aic32x4_register_clocks(dev, aic32x4->mclk_name);
if (ret)
return ret;
return 0; return 0;
} }
EXPORT_SYMBOL(aic32x4_probe); EXPORT_SYMBOL(aic32x4_probe);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment