Commit 354caf58 authored by Mark Brown's avatar Mark Brown

Merge series "Codec workaround" from Michael Sit Wei Hong <michael.wei.hong.sit@intel.com>:

This patch series enables some features on the tlv3204 codec and also fixes some issues faced while testing

v2: Fixed the build error from snd_soc_component_read32
v1: initial ASoC: codec: tlv3204: Codec workaround series

Michael Sit Wei Hong (3):
  ASoC: codec: tlv3204: Enable 24 bit audio support
  ASoC: codec: tlv3204: Increased maximum supported channels
  ASoC: codec: tlv3204: Moving GPIO reset and add ADC reset

 sound/soc/codecs/tlv320aic32x4.c | 60 +++++++++++++++++++++++---------
 1 file changed, 44 insertions(+), 16 deletions(-)

--
2.17.1
parents 4782e6cc 9d4befff
...@@ -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"),
...@@ -665,7 +688,8 @@ static int aic32x4_set_processing_blocks(struct snd_soc_component *component, ...@@ -665,7 +688,8 @@ static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
} }
static int aic32x4_setup_clocks(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; u8 aosr;
u16 dosr; u16 dosr;
...@@ -753,7 +777,8 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component, ...@@ -753,7 +777,8 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component,
dosr); dosr);
clk_set_rate(clocks[5].clk, clk_set_rate(clocks[5].clk,
sample_rate * 32); sample_rate * channel *
bit_depth);
return 0; return 0;
} }
} }
...@@ -775,9 +800,11 @@ static int aic32x4_hw_params(struct snd_pcm_substream *substream, ...@@ -775,9 +800,11 @@ static int aic32x4_hw_params(struct snd_pcm_substream *substream,
u8 iface1_reg = 0; u8 iface1_reg = 0;
u8 dacsetup_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: case 16:
iface1_reg |= (AIC32X4_WORD_LEN_16BITS << iface1_reg |= (AIC32X4_WORD_LEN_16BITS <<
AIC32X4_IFACE1_DATALEN_SHIFT); AIC32X4_IFACE1_DATALEN_SHIFT);
...@@ -862,7 +889,8 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component, ...@@ -862,7 +889,8 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component,
#define AIC32X4_RATES SNDRV_PCM_RATE_8000_192000 #define AIC32X4_RATES SNDRV_PCM_RATE_8000_192000
#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ #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 = { static const struct snd_soc_dai_ops aic32x4_ops = {
.hw_params = aic32x4_hw_params, .hw_params = aic32x4_hw_params,
...@@ -883,7 +911,7 @@ static struct snd_soc_dai_driver aic32x4_dai = { ...@@ -883,7 +911,7 @@ static struct snd_soc_dai_driver aic32x4_dai = {
.capture = { .capture = {
.stream_name = "Capture", .stream_name = "Capture",
.channels_min = 1, .channels_min = 1,
.channels_max = 2, .channels_max = 8,
.rates = AIC32X4_RATES, .rates = AIC32X4_RATES,
.formats = AIC32X4_FORMATS,}, .formats = AIC32X4_FORMATS,},
.ops = &aic32x4_ops, .ops = &aic32x4_ops,
...@@ -953,12 +981,6 @@ static int aic32x4_component_probe(struct snd_soc_component *component) ...@@ -953,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)
...@@ -1191,10 +1213,6 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap) ...@@ -1191,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");
...@@ -1216,6 +1234,16 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap) ...@@ -1216,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