ASoC: nau8540: reset state machine for channel phase sync
authorJohn Hsu <KCHSU0@nuvoton.com>
Tue, 7 Nov 2017 07:23:17 +0000 (15:23 +0800)
committerMark Brown <broonie@kernel.org>
Tue, 7 Nov 2017 10:28:35 +0000 (11:28 +0100)
The four channel ADCs in NAU85L40 have difference control registers,
it is hard to synchronous these four channels without correct sequence.
The phase difference will not be a constant and not to conjecture easily.
It may be 2.55 degree, or more ,or less.
Intended to prevent phase difference of channels, the solution as follows:
(1)Channel_Sync need to be enabled.
(2)Do soft reset without affecting register when recording done.

Signed-off-by: John Hsu <KCHSU0@nuvoton.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/nau8540.c
sound/soc/codecs/nau8540.h

index f9c9933acffb60ee50c9c7ec062e3cc278bedf60..c10cbffa63149a8b05d90bd3e31b0fd562da8c31 100644 (file)
@@ -233,6 +233,19 @@ static SOC_ENUM_SINGLE_DECL(
 static const struct snd_kcontrol_new digital_ch1_mux =
        SOC_DAPM_ENUM("Digital CH1 Select", digital_ch1_enum);
 
+static int aiftx_power_control(struct snd_soc_dapm_widget *w,
+               struct snd_kcontrol *k, int  event)
+{
+       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+       struct nau8540 *nau8540 = snd_soc_codec_get_drvdata(codec);
+
+       if (SND_SOC_DAPM_EVENT_OFF(event)) {
+               regmap_write(nau8540->regmap, NAU8540_REG_RST, 0x0001);
+               regmap_write(nau8540->regmap, NAU8540_REG_RST, 0x0000);
+       }
+       return 0;
+}
+
 static const struct snd_soc_dapm_widget nau8540_dapm_widgets[] = {
        SND_SOC_DAPM_SUPPLY("MICBIAS2", NAU8540_REG_MIC_BIAS, 11, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("MICBIAS1", NAU8540_REG_MIC_BIAS, 10, 0, NULL, 0),
@@ -270,7 +283,8 @@ static const struct snd_soc_dapm_widget nau8540_dapm_widgets[] = {
        SND_SOC_DAPM_MUX("Digital CH1 Mux",
                SND_SOC_NOPM, 0, 0, &digital_ch1_mux),
 
-       SND_SOC_DAPM_AIF_OUT("AIFTX", "Capture", 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_OUT_E("AIFTX", "Capture", 0, SND_SOC_NOPM, 0, 0,
+               aiftx_power_control, SND_SOC_DAPM_POST_PMD),
 };
 
 static const struct snd_soc_dapm_route nau8540_dapm_routes[] = {
@@ -710,9 +724,12 @@ static void nau8540_init_regs(struct nau8540 *nau8540)
        regmap_update_bits(regmap, NAU8540_REG_CLOCK_CTRL,
                NAU8540_CLK_ADC_EN | NAU8540_CLK_I2S_EN,
                NAU8540_CLK_ADC_EN | NAU8540_CLK_I2S_EN);
-       /* ADC OSR selection, CLK_ADC = Fs * OSR */
+       /* ADC OSR selection, CLK_ADC = Fs * OSR;
+        * Channel time alignment enable.
+        */
        regmap_update_bits(regmap, NAU8540_REG_ADC_SAMPLE_RATE,
-               NAU8540_ADC_OSR_MASK, NAU8540_ADC_OSR_64);
+               NAU8540_CH_SYNC | NAU8540_ADC_OSR_MASK,
+               NAU8540_CH_SYNC | NAU8540_ADC_OSR_64);
 }
 
 static int __maybe_unused nau8540_suspend(struct snd_soc_codec *codec)
index 5db5b224944dd12ceff7df4d8244bc7bfd8d48e1..14339f9bb01ac3526e340a2173771c5496f37438 100644 (file)
 #define NAU8540_TDM_TX_MASK            0xf
 
 /* ADC_SAMPLE_RATE (0x3A) */
+#define NAU8540_CH_SYNC                (0x1 << 14)
 #define NAU8540_ADC_OSR_MASK           0x3
 #define NAU8540_ADC_OSR_256            0x3
 #define NAU8540_ADC_OSR_128            0x2