ASoC: nau8825: Add a manually mechanism for detection failure
authorDavid Lin <CTLIN0@nuvoton.com>
Tue, 22 Nov 2022 07:38:56 +0000 (15:38 +0800)
committerMark Brown <broonie@kernel.org>
Tue, 22 Nov 2022 12:23:14 +0000 (12:23 +0000)
This patch is to use saradc to check the jack type when auto
detection is still failure.

Signed-off-by: David Lin <CTLIN0@nuvoton.com>
Link: https://lore.kernel.org/r/20221122073855.43024-2-CTLIN0@nuvoton.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/nau8825.c
sound/soc/codecs/nau8825.h

index ba7f5ec28609c83a9f7699091176b7a0b424e43c..4bffa9c20f2bcfefc8cebfe826d4cfead1a922e4 100644 (file)
@@ -1736,6 +1736,121 @@ static int nau8825_button_decode(int value)
        return buttons;
 }
 
+static int nau8825_high_imped_detection(struct nau8825 *nau8825)
+{
+       struct regmap *regmap = nau8825->regmap;
+       struct snd_soc_dapm_context *dapm = nau8825->dapm;
+       unsigned int adc_mg1, adc_mg2;
+
+       /* Initial phase */
+       regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL,
+                          NAU8825_SPKR_ENGND1 | NAU8825_SPKR_ENGND2 | NAU8825_SPKR_DWN1R |
+                          NAU8825_SPKR_DWN1L, NAU8825_SPKR_ENGND1 | NAU8825_SPKR_ENGND2);
+       regmap_update_bits(regmap, NAU8825_REG_ANALOG_CONTROL_1,
+                          NAU8825_TESTDACIN_MASK, NAU8825_TESTDACIN_GND);
+       regmap_write(regmap, NAU8825_REG_TRIM_SETTINGS, 0x6);
+       regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS,
+                          NAU8825_MICBIAS_LOWNOISE_MASK | NAU8825_MICBIAS_VOLTAGE_MASK,
+                          NAU8825_MICBIAS_LOWNOISE_EN);
+       regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL,
+                          NAU8825_SAR_INPUT_MASK | NAU8825_SAR_TRACKING_GAIN_MASK |
+                          NAU8825_SAR_HV_SEL_MASK | NAU8825_SAR_RES_SEL_MASK |
+                          NAU8825_SAR_COMPARE_TIME_MASK | NAU8825_SAR_SAMPLING_TIME_MASK,
+                          NAU8825_SAR_HV_SEL_VDDMIC | NAU8825_SAR_RES_SEL_70K);
+
+       snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
+       snd_soc_dapm_force_enable_pin(dapm, "SAR");
+       snd_soc_dapm_sync(dapm);
+
+       /* Configure settings for first reading of SARADC */
+       regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL,
+                          NAU8825_SPKR_ENGND1 | NAU8825_SPKR_ENGND2 | NAU8825_SPKR_DWN1R |
+                          NAU8825_SPKR_DWN1L, NAU8825_SPKR_ENGND2);
+       regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS,
+                          NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_JKR2,
+                          NAU8825_MICBIAS_JKR2);
+       regmap_read(regmap, NAU8825_REG_SARDOUT_RAM_STATUS, &adc_mg1);
+
+       /* Configure settings for second reading of SARADC */
+       regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS,
+                          NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_JKR2, 0);
+       regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL,
+                          NAU8825_SPKR_ENGND1 | NAU8825_SPKR_ENGND2 | NAU8825_SPKR_DWN1R |
+                          NAU8825_SPKR_DWN1L, NAU8825_SPKR_ENGND1 | NAU8825_SPKR_ENGND2 |
+                          NAU8825_SPKR_DWN1R | NAU8825_SPKR_DWN1L);
+       regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL,
+                          NAU8825_SPKR_ENGND1 | NAU8825_SPKR_ENGND2 | NAU8825_SPKR_DWN1R |
+                          NAU8825_SPKR_DWN1L, NAU8825_SPKR_ENGND1);
+       regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS,
+                          NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_JKR2,
+                          NAU8825_MICBIAS_JKSLV);
+       regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL,
+                          NAU8825_SAR_INPUT_MASK, NAU8825_SAR_INPUT_JKSLV);
+       regmap_read(regmap, NAU8825_REG_SARDOUT_RAM_STATUS, &adc_mg2);
+
+       /* Disable phase */
+       snd_soc_dapm_disable_pin(dapm, "SAR");
+       snd_soc_dapm_disable_pin(dapm, "MICBIAS");
+       snd_soc_dapm_sync(dapm);
+
+       regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS,
+                          NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_LOWNOISE_MASK |
+                          NAU8825_MICBIAS_VOLTAGE_MASK, nau8825->micbias_voltage);
+       regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL,
+                          NAU8825_SPKR_ENGND1 | NAU8825_SPKR_ENGND2 | NAU8825_SPKR_DWN1R |
+                          NAU8825_SPKR_DWN1L, NAU8825_SPKR_ENGND1 | NAU8825_SPKR_ENGND2 |
+                          NAU8825_SPKR_DWN1R | NAU8825_SPKR_DWN1L);
+       regmap_update_bits(regmap, NAU8825_REG_ANALOG_CONTROL_1,
+                          NAU8825_TESTDACIN_MASK, NAU8825_TESTDACIN_GND);
+       regmap_write(regmap, NAU8825_REG_TRIM_SETTINGS, 0);
+       regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL,
+                          NAU8825_SAR_TRACKING_GAIN_MASK | NAU8825_SAR_HV_SEL_MASK,
+                          nau8825->sar_voltage << NAU8825_SAR_TRACKING_GAIN_SFT);
+       regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL,
+                          NAU8825_SAR_COMPARE_TIME_MASK | NAU8825_SAR_SAMPLING_TIME_MASK,
+                          (nau8825->sar_compare_time << NAU8825_SAR_COMPARE_TIME_SFT) |
+                          (nau8825->sar_sampling_time << NAU8825_SAR_SAMPLING_TIME_SFT));
+       dev_dbg(nau8825->dev, "adc_mg1:%x, adc_mg2:%x\n", adc_mg1, adc_mg2);
+
+       /* Confirmation phase */
+       if (adc_mg1 > adc_mg2) {
+               dev_dbg(nau8825->dev, "OMTP (micgnd1) mic connected\n");
+
+               /* Unground MICGND1 */
+               regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL,
+                                  NAU8825_SPKR_ENGND1 | NAU8825_SPKR_ENGND2,
+                                  NAU8825_SPKR_ENGND2);
+               /* Attach 2kOhm Resistor from MICBIAS to MICGND1 */
+               regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS,
+                                  NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_JKR2,
+                                  NAU8825_MICBIAS_JKR2);
+               /* Attach SARADC to MICGND1 */
+               regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL,
+                                  NAU8825_SAR_INPUT_MASK,
+                                  NAU8825_SAR_INPUT_JKR2);
+       } else if (adc_mg1 < adc_mg2) {
+               dev_dbg(nau8825->dev, "CTIA (micgnd2) mic connected\n");
+
+               /* Unground MICGND2 */
+               regmap_update_bits(regmap, NAU8825_REG_HSD_CTRL,
+                                  NAU8825_SPKR_ENGND1 | NAU8825_SPKR_ENGND2,
+                                  NAU8825_SPKR_ENGND1);
+               /* Attach 2kOhm Resistor from MICBIAS to MICGND2 */
+               regmap_update_bits(regmap, NAU8825_REG_MIC_BIAS,
+                                  NAU8825_MICBIAS_JKSLV | NAU8825_MICBIAS_JKR2,
+                                  NAU8825_MICBIAS_JKSLV);
+               /* Attach SARADC to MICGND2 */
+               regmap_update_bits(regmap, NAU8825_REG_SAR_CTRL,
+                                  NAU8825_SAR_INPUT_MASK,
+                                  NAU8825_SAR_INPUT_JKSLV);
+       } else {
+               dev_err(nau8825->dev, "Jack broken.\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int nau8825_jack_insert(struct nau8825 *nau8825)
 {
        struct regmap *regmap = nau8825->regmap;
@@ -1797,9 +1912,16 @@ static int nau8825_jack_insert(struct nau8825 *nau8825)
                snd_soc_dapm_sync(dapm);
                break;
        case 3:
-               /* detect error case */
-               dev_err(nau8825->dev, "detection error; disable mic function\n");
-               type = SND_JACK_HEADPHONE;
+               /* Detection failure case */
+               dev_warn(nau8825->dev,
+                        "Detection failure. Try the manually mechanism for jack type checking.\n");
+               if (!nau8825_high_imped_detection(nau8825)) {
+                       type = SND_JACK_HEADSET;
+                       snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
+                       snd_soc_dapm_force_enable_pin(dapm, "SAR");
+                       snd_soc_dapm_sync(dapm);
+               } else
+                       type = SND_JACK_HEADPHONE;
                break;
        }
 
index d84191a7beb21b09367ab1a2bb7073e1a7712690..0c3a446e0e1aed51aa1ad163b8031576d9b1e646 100644 (file)
 /* HSD_CTRL (0xc) */
 #define NAU8825_HSD_AUTO_MODE  (1 << 6)
 /* 0 - open, 1 - short to GND */
+#define NAU8825_SPKR_ENGND1    (1 << 3)
+#define NAU8825_SPKR_ENGND2    (1 << 2)
 #define NAU8825_SPKR_DWN1R     (1 << 1)
 #define NAU8825_SPKR_DWN1L     (1 << 0)
 
 #define NAU8825_SAR_INPUT_JKR2 (0 << 11)
 #define NAU8825_SAR_TRACKING_GAIN_SFT  8
 #define NAU8825_SAR_TRACKING_GAIN_MASK (0x7 << NAU8825_SAR_TRACKING_GAIN_SFT)
+#define NAU8825_SAR_HV_SEL_SFT         7
+#define NAU8825_SAR_HV_SEL_MASK                (1 << NAU8825_SAR_HV_SEL_SFT)
+#define NAU8825_SAR_HV_SEL_MICBIAS     (0 << NAU8825_SAR_HV_SEL_SFT)
+#define NAU8825_SAR_HV_SEL_VDDMIC      (1 << NAU8825_SAR_HV_SEL_SFT)
+#define NAU8825_SAR_RES_SEL_SFT                4
+#define NAU8825_SAR_RES_SEL_MASK       (0x7 << NAU8825_SAR_RES_SEL_SFT)
+#define NAU8825_SAR_RES_SEL_35K                (0 << NAU8825_SAR_RES_SEL_SFT)
+#define NAU8825_SAR_RES_SEL_70K                (1 << NAU8825_SAR_RES_SEL_SFT)
+#define NAU8825_SAR_RES_SEL_170K       (2 << NAU8825_SAR_RES_SEL_SFT)
+#define NAU8825_SAR_RES_SEL_360K       (3 << NAU8825_SAR_RES_SEL_SFT)
+#define NAU8825_SAR_RES_SEL_SHORTED    (4 << NAU8825_SAR_RES_SEL_SFT)
 #define NAU8825_SAR_COMPARE_TIME_SFT   2
 #define NAU8825_SAR_COMPARE_TIME_MASK  (3 << 2)
 #define NAU8825_SAR_SAMPLING_TIME_SFT  0
 #define NAU8825_BIAS_VMID_SEL_SFT      4
 #define NAU8825_BIAS_VMID_SEL_MASK     (3 << NAU8825_BIAS_VMID_SEL_SFT)
 
+/* ANALOG_CONTROL_1 (0x69) */
+#define NAU8825_TESTDACIN_SFT          14
+#define NAU8825_TESTDACIN_MASK         (0x3 << NAU8825_TESTDACIN_SFT)
+#define NAU8825_TESTDACIN_HIGH         (1 << NAU8825_TESTDACIN_SFT)
+#define NAU8825_TESTDACIN_LOW          (2 << NAU8825_TESTDACIN_SFT)
+#define NAU8825_TESTDACIN_GND          (3 << NAU8825_TESTDACIN_SFT)
+
 /* ANALOG_CONTROL_2 (0x6a) */
 #define NAU8825_HP_NON_CLASSG_CURRENT_2xADJ (1 << 12)
 #define NAU8825_DAC_CAPACITOR_MSB (1 << 1)
 /* MIC_BIAS (0x74) */
 #define NAU8825_MICBIAS_JKSLV  (1 << 14)
 #define NAU8825_MICBIAS_JKR2   (1 << 12)
+#define NAU8825_MICBIAS_LOWNOISE_SFT   10
+#define NAU8825_MICBIAS_LOWNOISE_MASK  (0x1 << NAU8825_MICBIAS_LOWNOISE_SFT)
+#define NAU8825_MICBIAS_LOWNOISE_EN    (0x1 << NAU8825_MICBIAS_LOWNOISE_SFT)
 #define NAU8825_MICBIAS_POWERUP_SFT    8
 #define NAU8825_MICBIAS_VOLTAGE_SFT    0
 #define NAU8825_MICBIAS_VOLTAGE_MASK   0x7