From dcd79364bff36ce1341a59be8142ded5b7da7d19 Mon Sep 17 00:00:00 2001 From: Michael Sit Wei Hong Date: Wed, 12 Aug 2020 17:46:29 +0800 Subject: ASoC: codec: tlv3204: Enable 24 bit audio support Enable 24 bit in 32 bit container audio support. Using the params_physical_width to differentiate 24 bit in 32 bit container and 24 bit in 24 bit container modes. Use the sample rate, bit depth and channel parameters to calculate the bit clock needed. Signed-off-by: Michael Sit Wei Hong Reviewed-by: Sia Jee Heng Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200812094631.4698-2-michael.wei.hong.sit@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 467802875c13..e3d12a7ea07a 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -665,7 +665,8 @@ static int aic32x4_set_processing_blocks(struct snd_soc_component *component, } static int aic32x4_setup_clocks(struct snd_soc_component *component, - unsigned int sample_rate) + unsigned int sample_rate, unsigned int channel, + unsigned int bit_depth) { u8 aosr; u16 dosr; @@ -753,7 +754,8 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component, dosr); clk_set_rate(clocks[5].clk, - sample_rate * 32); + sample_rate * channel * + bit_depth); return 0; } } @@ -775,9 +777,11 @@ static int aic32x4_hw_params(struct snd_pcm_substream *substream, u8 iface1_reg = 0; u8 dacsetup_reg = 0; - aic32x4_setup_clocks(component, params_rate(params)); + aic32x4_setup_clocks(component, params_rate(params), + params_channels(params), + params_physical_width(params)); - switch (params_width(params)) { + switch (params_physical_width(params)) { case 16: iface1_reg |= (AIC32X4_WORD_LEN_16BITS << AIC32X4_IFACE1_DATALEN_SHIFT); @@ -862,7 +866,8 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component, #define AIC32X4_RATES SNDRV_PCM_RATE_8000_192000 #define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ - | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) + | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_3LE \ + | SNDRV_PCM_FMTBIT_S32_LE) static const struct snd_soc_dai_ops aic32x4_ops = { .hw_params = aic32x4_hw_params, -- cgit v1.2.3 From d1c859d314d87c6f4dc09c3d7cf6f3ec9f44bcc5 Mon Sep 17 00:00:00 2001 From: Michael Sit Wei Hong Date: Wed, 12 Aug 2020 17:46:30 +0800 Subject: ASoC: codec: tlv3204: Increased maximum supported channels Increased maximum supported channel to 8 channels for audio capture running in TDM mode. Signed-off-by: Michael Sit Wei Hong Reviewed-by: Sia Jee Heng Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200812094631.4698-3-michael.wei.hong.sit@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index e3d12a7ea07a..6c2338ea5d8d 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -888,7 +888,7 @@ static struct snd_soc_dai_driver aic32x4_dai = { .capture = { .stream_name = "Capture", .channels_min = 1, - .channels_max = 2, + .channels_max = 8, .rates = AIC32X4_RATES, .formats = AIC32X4_FORMATS,}, .ops = &aic32x4_ops, -- cgit v1.2.3 From 9d4befff5a959e5f2f94357b3554a6929f596e15 Mon Sep 17 00:00:00 2001 From: Michael Sit Wei Hong Date: Wed, 12 Aug 2020 17:46:31 +0800 Subject: 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: Michael Sit Wei Hong Reviewed-by: Sia Jee Heng Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20200812094631.4698-4-michael.wei.hong.sit@intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 47 ++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 12 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 6c2338ea5d8d..8dcea566b375 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -50,6 +50,28 @@ struct aic32x4_priv { 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, struct snd_kcontrol *kcontrol, int event) { @@ -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_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("HPR"), @@ -665,8 +688,8 @@ static int aic32x4_set_processing_blocks(struct snd_soc_component *component, } static int aic32x4_setup_clocks(struct snd_soc_component *component, - unsigned int sample_rate, unsigned int channel, - unsigned int bit_depth) + unsigned int sample_rate, unsigned int channel, + unsigned int bit_depth) { u8 aosr; u16 dosr; @@ -958,12 +981,6 @@ static int aic32x4_component_probe(struct snd_soc_component *component) if (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); if (aic32x4->setup) @@ -1196,10 +1213,6 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap) aic32x4->mclk_name = "mclk"; } - ret = aic32x4_register_clocks(dev, aic32x4->mclk_name); - if (ret) - return ret; - if (gpio_is_valid(aic32x4->rstn_gpio)) { ret = devm_gpio_request_one(dev, aic32x4->rstn_gpio, GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); @@ -1221,6 +1234,16 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap) 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; } EXPORT_SYMBOL(aic32x4_probe); -- cgit v1.2.3