Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3a13144 authored by Phani Kumar Uppalapati's avatar Phani Kumar Uppalapati
Browse files

ASoC: wcd9xxx: Correct RCO enable and disable sequence



Correct RCO enable and disable sequence. Add bandgap
enable before setting RCO and disable bandgap after RCO
is turned off. Also, codec internal clock gating for master
clock cannot be disabled in order to avoid codec digital state
machine from going to bad state which may result into intermittent
audio loss.

Change-Id: Ife4994e4ca5abd6e69b85fdb1a632441b682969a
Signed-off-by: default avatarPhani Kumar Uppalapati <phaniu@codeaurora.org>
parent 5c3bdb89
Loading
Loading
Loading
Loading
+57 −25
Original line number Diff line number Diff line
@@ -153,6 +153,13 @@ static struct afe_param_id_cdc_aanc_version tapan_cdc_aanc_version = {
	.aanc_hw_version        = AANC_HW_BLOCK_VERSION_2,
};

enum tapan_codec_type {
	WCD9306,
	WCD9302,
};

static enum tapan_codec_type codec_ver;

enum {
	AIF1_PB = 0,
	AIF1_CAP,
@@ -5455,7 +5462,25 @@ static void tapan_enable_config_rco(struct wcd9xxx *core, bool enable)
	struct wcd9xxx_core_resource *core_res = &core->core_res;

	if (enable) {
		/* Enable RC Oscillator */
		/*
		 * Enable Bandgap
		 * sleep required by codec hardware to enable bandgap
		 */
		wcd9xxx_reg_update(core, WCD9XXX_A_BIAS_CENTRAL_BG_CTL,
				   0x80, 0x80);
		wcd9xxx_reg_update(core, WCD9XXX_A_BIAS_CENTRAL_BG_CTL,
				   0x04, 0x04);
		wcd9xxx_reg_update(core, WCD9XXX_A_BIAS_CENTRAL_BG_CTL,
				   0x01, 0x01);
		usleep_range(1000, 1100);
		wcd9xxx_reg_update(core, WCD9XXX_A_BIAS_CENTRAL_BG_CTL,
				   0x80, 0x00);

		/*
		 * Enable RC Oscillator
		 * Add sleep required by codec hardware after each register
		 * write to enable RC oscillator
		 */
		wcd9xxx_reg_update(core, WCD9XXX_A_RC_OSC_FREQ, 0x10, 0x00);
		wcd9xxx_reg_write(core_res, WCD9XXX_A_BIAS_OSC_BG_CTL, 0x17);
		usleep_range(5, 5);
@@ -5481,29 +5506,39 @@ static void tapan_enable_config_rco(struct wcd9xxx *core, bool enable)
		/*
		 * Disable RC oscillator, reset the registers to their
		 * default values
		 * Add sleep required by codec hardware after each register
		 * write to disable RC oscillator
		 */
		wcd9xxx_reg_write(core_res, WCD9XXX_A_CDC_CLK_MCLK_CTL, 0x00);
		wcd9xxx_reg_write(core_res, WCD9XXX_A_CLK_BUFF_EN2, 0x02);
		wcd9xxx_reg_write(core_res, WCD9XXX_A_CLK_BUFF_EN1, 0x04);
		wcd9xxx_reg_write(core_res, WCD9XXX_A_RC_OSC_TEST, 0x0A);
		wcd9xxx_reg_write(core_res, WCD9XXX_A_RC_OSC_FREQ, 0x46);
		wcd9xxx_reg_update(core, WCD9XXX_A_CLK_BUFF_EN2, 0x04, 0x00);
		usleep_range(50, 100);
		wcd9xxx_reg_update(core, WCD9XXX_A_CLK_BUFF_EN2, 0x02, 0x02);
		wcd9xxx_reg_update(core, WCD9XXX_A_CLK_BUFF_EN1, 0x05, 0x00);
		usleep_range(50, 100);

		wcd9xxx_reg_update(core, WCD9XXX_A_RC_OSC_FREQ, 0x80, 0x00);
		usleep_range(10, 50);
		wcd9xxx_reg_write(core_res, WCD9XXX_A_BIAS_OSC_BG_CTL, 0x16);
		/* Disable Bandgap and wait 100us till it gets disabled */
		wcd9xxx_reg_update(core, WCD9XXX_A_BIAS_CENTRAL_BG_CTL,
				   0x03, 0x00);
		usleep_range(100, 150);
	}

}

static bool tapan_check_wcd9306(struct device *cdc_dev, bool sensed)
static enum tapan_codec_type tapan_get_codec_ver(struct device *cdc_dev,
						 bool sensed)
{
	struct wcd9xxx *core = dev_get_drvdata(cdc_dev->parent);
	u8 reg_val;
	bool ret = true;
	enum tapan_codec_type cdc_type = WCD9306;
	unsigned long timeout;
	bool timedout;
	struct wcd9xxx_core_resource *core_res = &core->core_res;

	if (!core) {
		dev_err(cdc_dev, "%s: core not initialized\n", __func__);
		return -EINVAL;
		return cdc_type;
	}

	tapan_enable_config_rco(core, 1);
@@ -5523,12 +5558,13 @@ static bool tapan_check_wcd9306(struct device *cdc_dev, bool sensed)
	if (wcd9xxx_reg_read(core_res, TAPAN_A_QFUSE_DATA_OUT1) ||
	    wcd9xxx_reg_read(core_res, TAPAN_A_QFUSE_DATA_OUT2)) {
		dev_info(cdc_dev, "%s: wcd9302 detected\n", __func__);
		ret = false;
		cdc_type = WCD9302;
	} else
		dev_info(cdc_dev, "%s: wcd9306 detected\n", __func__);

	tapan_enable_config_rco(core, 0);
	return ret;

	return cdc_type;
};

static int tapan_codec_probe(struct snd_soc_codec *codec)
@@ -5653,7 +5689,7 @@ static int tapan_codec_probe(struct snd_soc_codec *codec)
		tapan_init_slim_slave_cfg(codec);
	}

	if (tapan_check_wcd9306(codec->dev, false) == true) {
	if (codec_ver == WCD9306) {
		snd_soc_add_codec_controls(codec, tapan_9306_snd_controls,
					   ARRAY_SIZE(tapan_9306_snd_controls));
		snd_soc_dapm_new_controls(dapm, tapan_9306_dapm_widgets,
@@ -5678,11 +5714,13 @@ static int tapan_codec_probe(struct snd_soc_codec *codec)

	atomic_set(&kp_tapan_priv, (unsigned long)tapan);
	mutex_lock(&dapm->codec->mutex);
	if (codec_ver == WCD9306) {
		snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
		snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
		snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
		snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
		snd_soc_dapm_disable_pin(dapm, "ANC EAR");
	}
	snd_soc_dapm_sync(dapm);
	mutex_unlock(&dapm->codec->mutex);

@@ -5775,16 +5813,10 @@ static const struct dev_pm_ops tapan_pm_ops = {
static int tapan_probe(struct platform_device *pdev)
{
	int ret = 0;
	bool is_wcd9306;

	is_wcd9306 = tapan_check_wcd9306(&pdev->dev, false);
	if (is_wcd9306 < 0) {
		dev_info(&pdev->dev, "%s: cannot find codec type, default to 9306\n",
			 __func__);
		is_wcd9306 = true;
	}
	codec_ver = tapan_get_codec_ver(&pdev->dev, false);

	if (!is_wcd9306) {
	if (codec_ver == WCD9302) {
		if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
			ret = snd_soc_register_codec(&pdev->dev,
				&soc_codec_dev_tapan,