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

Commit 738c18d6 authored by Bhalchandra Gajare's avatar Bhalchandra Gajare
Browse files

ASoC: wcd9xxx: Enable MBHC TxFE when micbias is enabled



When micbias is turned ON for audio recording with headset
plugged in, there can be possible noise on the recorded
data due to micbias polling for button detection. To
avoid the noise on audio recording, it is required to
enable the MBHC TxFE (Front-End). Add support to enable
MBHC TxFE when micbias is being enabled for audio recording.

CRs-fixed: 522829
Change-Id: I0689982edab9204aa4f833e59f979f38d6d34418
Signed-off-by: default avatarBhalchandra Gajare <gajare@codeaurora.org>
parent dc077d46
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -1577,15 +1577,20 @@ static int msm8x10_wcd_codec_enable_micbias(struct snd_soc_dapm_widget *w,
	struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_codec *codec = w->codec;
	struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
	u16 micb_int_reg;
	char *internal1_text = "Internal1";
	char *internal2_text = "Internal2";
	char *internal3_text = "Internal3";
	enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on;

	dev_dbg(codec->dev, "%s %d\n", __func__, event);
	switch (w->reg) {
	case MSM8X10_WCD_A_MICB_1_CTL:
		micb_int_reg = MSM8X10_WCD_A_MICB_1_INT_RBIAS;
		e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON;
		e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON;
		e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF;
		break;
	default:
		dev_err(codec->dev,
@@ -1596,6 +1601,9 @@ static int msm8x10_wcd_codec_enable_micbias(struct snd_soc_dapm_widget *w,

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		/* Let MBHC module know micbias is about to turn ON */
		wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_pre_on);

		if (strnstr(w->name, internal1_text, 30))
			snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x80);
		else if (strnstr(w->name, internal2_text, 30))
@@ -1605,8 +1613,13 @@ static int msm8x10_wcd_codec_enable_micbias(struct snd_soc_dapm_widget *w,
		break;
	case SND_SOC_DAPM_POST_PMU:
		usleep_range(20000, 20100);
		/* Let MBHC module know so micbias is on */
		wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_on);
		break;
	case SND_SOC_DAPM_POST_PMD:
		/* Let MBHC module know so micbias switch to be off */
		wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_off);

		if (strnstr(w->name, internal1_text, 30))
			snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
		else if (strnstr(w->name, internal2_text, 30))
@@ -2649,6 +2662,12 @@ static void msm8x10_wcd_mbhc_clk_gate(struct snd_soc_codec *codec,
	snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_TOP_CLK_CTL, 0x10, 0x10);
}

static void msm8x10_wcd_mbhc_txfe(struct snd_soc_codec *codec, bool on)
{
	snd_soc_update_bits(codec, MSM8X10_WCD_A_TX_7_MBHC_EN_ATEST_CTRL,
			    0x80, on ? 0x80 : 0x00);
}

static const struct wcd9xxx_mbhc_cb mbhc_cb = {
	.enable_mux_bias_block = msm8x10_wcd_enable_mux_bias_block,
	.cfilt_fast_mode = msm8x10_wcd_put_cfilt_fast_mode,
@@ -2659,6 +2678,7 @@ static const struct wcd9xxx_mbhc_cb mbhc_cb = {
	.free_irq = msm8x10_wcd_free_irq,
	.get_cdc_type = msm8x10_wcd_get_cdc_type,
	.enable_clock_gate = msm8x10_wcd_mbhc_clk_gate,
	.enable_mbhc_txfe = msm8x10_wcd_mbhc_txfe,
};

static void delayed_hs_detect_fn(struct work_struct *work)
+30 −7
Original line number Diff line number Diff line
@@ -4050,6 +4050,15 @@ static int wcd9xxx_get_mbhc_cfilt_sel(struct wcd9xxx_mbhc *mbhc)
	return cfilt;
}

static void wcd9xxx_enable_mbhc_txfe(struct wcd9xxx_mbhc *mbhc, bool on)
{
	if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mbhc_txfe)
		mbhc->mbhc_cb->enable_mbhc_txfe(mbhc->codec, on);
	else
		snd_soc_update_bits(mbhc->codec, WCD9XXX_A_TX_7_MBHC_TEST_CTL,
				    0x40, on ? 0x40 : 0x00);
}

static int wcd9xxx_event_notify(struct notifier_block *self, unsigned long val,
				void *data)
{
@@ -4067,14 +4076,22 @@ static int wcd9xxx_event_notify(struct notifier_block *self, unsigned long val,
	case WCD9XXX_EVENT_PRE_MICBIAS_2_ON:
	case WCD9XXX_EVENT_PRE_MICBIAS_3_ON:
	case WCD9XXX_EVENT_PRE_MICBIAS_4_ON:
		if (mbhc->mbhc_cfg->micbias == wcd9xxx_event_to_micbias(event))
		if (mbhc->mbhc_cfg && mbhc->mbhc_cfg->micbias ==
		    wcd9xxx_event_to_micbias(event)) {
			wcd9xxx_switch_micbias(mbhc, 0);
			/*
			 * Enable MBHC TxFE whenever  micbias is
			 * turned ON and polling is active
			 */
			if (mbhc->polling_active)
				wcd9xxx_enable_mbhc_txfe(mbhc, true);
		}
		break;
	case WCD9XXX_EVENT_POST_MICBIAS_1_ON:
	case WCD9XXX_EVENT_POST_MICBIAS_2_ON:
	case WCD9XXX_EVENT_POST_MICBIAS_3_ON:
	case WCD9XXX_EVENT_POST_MICBIAS_4_ON:
		if (mbhc->mbhc_cfg->micbias ==
		if (mbhc->mbhc_cfg && mbhc->mbhc_cfg->micbias ==
		    wcd9xxx_event_to_micbias(event) &&
		    wcd9xxx_mbhc_polling(mbhc)) {
			/* if polling is on, restart it */
@@ -4086,11 +4103,17 @@ static int wcd9xxx_event_notify(struct notifier_block *self, unsigned long val,
	case WCD9XXX_EVENT_POST_MICBIAS_2_OFF:
	case WCD9XXX_EVENT_POST_MICBIAS_3_OFF:
	case WCD9XXX_EVENT_POST_MICBIAS_4_OFF:
		if (mbhc->mbhc_cfg->micbias ==
		    wcd9xxx_event_to_micbias(event) &&
		    (mbhc->event_state &
		     (1 << MBHC_EVENT_PA_HPHL | 1 << MBHC_EVENT_PA_HPHR)))
		if (mbhc->mbhc_cfg && mbhc->mbhc_cfg->micbias ==
		    wcd9xxx_event_to_micbias(event)) {
			if (mbhc->event_state &
			   (1 << MBHC_EVENT_PA_HPHL | 1 << MBHC_EVENT_PA_HPHR))
				wcd9xxx_switch_micbias(mbhc, 1);
			/*
			 * Disable MBHC TxFE, in case it was enabled
			 * earlier when micbias was enabled.
			 */
			wcd9xxx_enable_mbhc_txfe(mbhc, false);
		}
		break;
	/* PA usage change */
	case WCD9XXX_EVENT_PRE_HPHL_PA_ON:
+1 −0
Original line number Diff line number Diff line
@@ -250,6 +250,7 @@ struct wcd9xxx_mbhc_cb {
	int (*setup_zdet) (struct wcd9xxx_mbhc *,
			   enum mbhc_impedance_detect_stages stage);
	void (*compute_impedance) (s16 *, s16 *, uint32_t *, uint32_t *);
	void (*enable_mbhc_txfe) (struct snd_soc_codec *, bool);
};

struct wcd9xxx_mbhc {