ASOC: codecs: ES8326: Add calibration support for version_b

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>
This commit is contained in:
Zhu Ning 2023-07-17 11:32:22 +08:00 committed by Mark Brown
parent ac20a73d76
commit 0663286e58
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View 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 */