Unverified Commit 0663286e authored by Zhu Ning's avatar Zhu Ning Committed by Mark Brown
Browse files

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: default avatarZhu Ning <zhuning0077@gmail.com>
Link: https://lore.kernel.org/r/20230717033223.42506-4-zhuning0077@gmail.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent ac20a73d
Loading
Loading
Loading
Loading
+68 −15
Original line number Diff line number Diff line
@@ -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 @@ static irqreturn_t es8326_irq(int irq, void *dev_id)
	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 */