ASOC: codecs: ES8326: Add calibration support for version_b
authorZhu Ning <zhuning0077@gmail.com>
Mon, 17 Jul 2023 03:32:22 +0000 (11:32 +0800)
committerMark Brown <broonie@kernel.org>
Tue, 25 Jul 2023 11:11:53 +0000 (12:11 +0100)
Version_b requires a new way of calibrating headset offset. A new
calibration function is added.

Signed-off-by: Zhu Ning <zhuning0077@gmail.com>
Link: https://lore.kernel.org/r/20230717033223.42506-4-zhuning0077@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/es8326.c

index ffb61a3cbfe4e949a23baf271e64cb95bb85e7b2..8ffabc8cd33e4fc42c4a0e5c6e0e16240e68a71d 100644 (file)
@@ -388,6 +388,7 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction)
 {
        struct snd_soc_component *component = dai->component;
        struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+       unsigned int offset_l, offset_r;
 
        if (mute) {
                regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_OFF);
@@ -398,10 +399,16 @@ static int es8326_mute(struct snd_soc_dai *dai, int mute, int direction)
                if (!es8326->calibrated) {
                        regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_FORCE_CAL);
                        msleep(30);
+                       regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_OFF);
+                       regmap_read(es8326->regmap, ES8326_HPL_OFFSET_INI, &offset_l);
+                       regmap_read(es8326->regmap, ES8326_HPR_OFFSET_INI, &offset_r);
+                       regmap_write(es8326->regmap, ES8326_HP_OFFSET_CAL, 0x8c);
+                       regmap_write(es8326->regmap, ES8326_HPL_OFFSET_INI, offset_l);
+                       regmap_write(es8326->regmap, ES8326_HPR_OFFSET_INI, offset_r);
                        es8326->calibrated = true;
                }
                regmap_write(es8326->regmap, ES8326_HP_DRIVER, 0xa0);
-               regmap_write(es8326->regmap, ES8326_HP_VOL, 0x00);
+               regmap_write(es8326->regmap, ES8326_HP_VOL, 0x80);
                regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_ON);
                regmap_update_bits(es8326->regmap, ES8326_DAC_MUTE,
                                ES8326_MUTE_MASK, ~(ES8326_MUTE));
@@ -420,15 +427,17 @@ static int es8326_set_bias_level(struct snd_soc_component *codec,
                ret = clk_prepare_enable(es8326->mclk);
                if (ret)
                        return ret;
-               regmap_write(es8326->regmap, ES8326_RESET, ES8326_PWRUP_SEQ_EN);
-               regmap_write(es8326->regmap, ES8326_INTOUT_IO, 0x45);
+
+               regmap_write(es8326->regmap, ES8326_RESET, 0x9f);
+               msleep(20);
+               regmap_update_bits(es8326->regmap, ES8326_DAC_DSM, 0x01, 0x00);
+               regmap_write(es8326->regmap, ES8326_INTOUT_IO, es8326->interrupt_clk);
                regmap_write(es8326->regmap, ES8326_SDINOUT1_IO,
                            (ES8326_IO_DMIC_CLK << ES8326_SDINOUT1_SHIFT));
-               regmap_write(es8326->regmap, ES8326_SDINOUT23_IO, ES8326_IO_INPUT);
-               regmap_write(es8326->regmap, ES8326_CLK_RESAMPLE, 0x05);
-               regmap_write(es8326->regmap, ES8326_VMIDSEL, 0x02);
+               regmap_write(es8326->regmap, ES8326_VMIDSEL, 0x0E);
                regmap_write(es8326->regmap, ES8326_PGA_PDN, 0x40);
-               regmap_write(es8326->regmap, ES8326_DAC2HPMIX, 0xAA);
+               regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x00);
+               regmap_update_bits(es8326->regmap,  ES8326_CLK_CTL, 0x20, 0x20);
                regmap_write(es8326->regmap, ES8326_RESET, ES8326_CSM_ON);
                break;
        case SND_SOC_BIAS_PREPARE:
@@ -437,15 +446,10 @@ static int es8326_set_bias_level(struct snd_soc_component *codec,
                break;
        case SND_SOC_BIAS_OFF:
                clk_disable_unprepare(es8326->mclk);
-               regmap_write(es8326->regmap, ES8326_DAC2HPMIX, 0x11);
-               regmap_write(es8326->regmap, ES8326_RESET, ES8326_CSM_OFF);
-               regmap_write(es8326->regmap, ES8326_PGA_PDN, 0xF8);
+               regmap_write(es8326->regmap, ES8326_ANA_PDN, 0x3b);
                regmap_write(es8326->regmap, ES8326_VMIDSEL, 0x00);
-               regmap_write(es8326->regmap, ES8326_INT_SOURCE, 0x08);
+               regmap_update_bits(es8326->regmap, ES8326_CLK_CTL, 0x20, 0x00);
                regmap_write(es8326->regmap, ES8326_SDINOUT1_IO, ES8326_IO_INPUT);
-               regmap_write(es8326->regmap, ES8326_SDINOUT23_IO, ES8326_IO_INPUT);
-               regmap_write(es8326->regmap, ES8326_RESET,
-                            ES8326_CODEC_RESET | ES8326_PWRUP_SEQ_EN);
                break;
        }
 
@@ -635,6 +639,54 @@ out:
        return IRQ_HANDLED;
 }
 
+static int es8326_calibrate(struct snd_soc_component *component)
+{
+       struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
+       unsigned int reg;
+       unsigned int offset_l, offset_r;
+
+       regmap_read(es8326->regmap, ES8326_CHIP_VERSION, &reg);
+       es8326->version = reg;
+
+       if ((es8326->version == ES8326_VERSION_B) && (es8326->calibrated == false)) {
+               dev_dbg(component->dev, "ES8326_VERSION_B, calibrating\n");
+               regmap_write(es8326->regmap, ES8326_CLK_INV, 0xc0);
+               regmap_write(es8326->regmap, ES8326_CLK_DIV1, 0x01);
+               regmap_write(es8326->regmap, ES8326_CLK_DLL, 0x30);
+               regmap_write(es8326->regmap, ES8326_CLK_MUX, 0xed);
+               regmap_write(es8326->regmap, ES8326_CLK_TRI, 0xc1);
+               regmap_write(es8326->regmap, ES8326_DAC_MUTE, 0x03);
+               regmap_write(es8326->regmap, ES8326_ANA_VSEL, 0x7f);
+               regmap_write(es8326->regmap, ES8326_VMIDLOW, 0x33);
+               regmap_write(es8326->regmap, ES8326_DAC2HPMIX, 0x88);
+               regmap_write(es8326->regmap, ES8326_HP_VOL, 0x80);
+               regmap_write(es8326->regmap, ES8326_HP_OFFSET_CAL, 0x8c);
+               regmap_write(es8326->regmap, ES8326_RESET, 0xc0);
+               usleep_range(15000, 20000);
+
+               regmap_write(es8326->regmap, ES8326_HP_OFFSET_CAL, ES8326_HP_OFF);
+               regmap_read(es8326->regmap, ES8326_CSM_MUTE_STA, &reg);
+               if ((reg & 0xf0) != 0x40)
+                       msleep(50);
+
+               regmap_write(es8326->regmap, ES8326_HP_CAL, 0xd4);
+               msleep(200);
+               regmap_write(es8326->regmap, ES8326_HP_CAL, 0x4d);
+               msleep(200);
+               regmap_write(es8326->regmap, ES8326_HP_CAL, ES8326_HP_OFF);
+               regmap_read(es8326->regmap, ES8326_HPL_OFFSET_INI, &offset_l);
+               regmap_read(es8326->regmap, ES8326_HPR_OFFSET_INI, &offset_r);
+               regmap_write(es8326->regmap, ES8326_HP_OFFSET_CAL, 0x8c);
+               regmap_write(es8326->regmap, ES8326_HPL_OFFSET_INI, offset_l);
+               regmap_write(es8326->regmap, ES8326_HPR_OFFSET_INI, offset_r);
+               regmap_write(es8326->regmap, ES8326_CLK_INV, 0x00);
+
+               es8326->calibrated = true;
+       }
+
+       return 0;
+}
+
 static int es8326_resume(struct snd_soc_component *component)
 {
        struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component);
@@ -673,7 +725,8 @@ static int es8326_resume(struct snd_soc_component *component)
        regmap_write(es8326->regmap, ES8326_CLK_VMIDS1, 0xc4);
        regmap_write(es8326->regmap, ES8326_CLK_VMIDS2, 0x81);
        regmap_write(es8326->regmap, ES8326_CLK_CAL_TIME, 0x00);
-
+       /* calibrate for B version */
+       es8326_calibrate(component);
        /* turn off headphone out */
        regmap_write(es8326->regmap, ES8326_HP_CAL, 0x00);
        /* set ADC and DAC in low power mode */