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

Commit 25f75cf1 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: wcd: disable PA when headset is removed"

parents 9f441c72 0805dd59
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <sound/tlv.h>
#include <soc/qcom/subsystem_notif.h>
#include "msm8x16-wcd.h"
#include "wcd-mbhc-v2.h"
#include "msm8916-wcd-irq.h"
#include "msm8x16_wcd_registers.h"
#include "../msm/qdsp6v2/q6core.h"
@@ -2087,6 +2088,7 @@ static int msm8x16_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,
			      struct snd_kcontrol *kcontrol, int event)
{
	struct snd_soc_codec *codec = w->codec;
	struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);

	dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);

@@ -2129,6 +2131,13 @@ static int msm8x16_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,
		}
		break;
	case SND_SOC_DAPM_POST_PMD:
		if (w->shift == 5) {
			clear_bit(WCD_MBHC_HPHL_PA_OFF_ACK,
				&msm8x16_wcd->mbhc.hph_pa_dac_state);
		} else if (w->shift == 4) {
			clear_bit(WCD_MBHC_HPHR_PA_OFF_ACK,
				&msm8x16_wcd->mbhc.hph_pa_dac_state);
		}
		snd_soc_update_bits(codec,
				MSM8X16_WCD_A_ANALOG_NCP_FBCTRL, 0x20, 0x00);
		usleep_range(4000, 4100);
+63 −0
Original line number Diff line number Diff line
@@ -107,6 +107,67 @@ static void hphlocp_off_report(struct wcd_mbhc *mbhc, u32 jack_status)
			    mbhc->intr_ids->hph_left_ocp);
}

static void wcd_mbhc_clr_and_turnon_hph_padac(struct wcd_mbhc *mbhc)
{
	bool pa_turned_on = false;
	u8 wg_time;
	struct snd_soc_codec *codec = mbhc->codec;

	wg_time = snd_soc_read(codec, MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_WG_TIME);
	wg_time += 1;

	if (test_and_clear_bit(WCD_MBHC_HPHR_PA_OFF_ACK,
			       &mbhc->hph_pa_dac_state)) {
		pr_debug("%s: HPHR clear flag and enable PA\n", __func__);
		snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN,
				    0x10, 0x10);
		pa_turned_on = true;
	}
	if (test_and_clear_bit(WCD_MBHC_HPHL_PA_OFF_ACK,
			       &mbhc->hph_pa_dac_state)) {
		pr_debug("%s: HPHL clear flag and enable PA\n", __func__);
		snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN,
				    0x20, 0x20);
		pa_turned_on = true;
	}

	if (pa_turned_on) {
		pr_debug("%s: PA was turned off by MBHC and not by DAPM\n",
			 __func__);
		usleep_range(wg_time * 1000, wg_time * 1000 + 50);
	}
}

static bool wcd_mbhc_is_hph_pa_on(struct snd_soc_codec *codec)
{
	u8 hph_reg_val = 0;
	hph_reg_val = snd_soc_read(codec, MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN);

	return (hph_reg_val & 0x30) ? true : false;
}

static void wcd_mbhc_set_and_turnoff_hph_padac(struct wcd_mbhc *mbhc)
{
	u8 wg_time;
	struct snd_soc_codec *codec = mbhc->codec;

	wg_time = snd_soc_read(codec, MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_WG_TIME);
	wg_time += 1;

	/* If headphone PA is on, check if userspace receives
	* removal event to sync-up PA's state */
	if (wcd_mbhc_is_hph_pa_on(codec)) {
		pr_debug("%s PA is on, setting PA_OFF_ACK\n", __func__);
		set_bit(WCD_MBHC_HPHL_PA_OFF_ACK, &mbhc->hph_pa_dac_state);
		set_bit(WCD_MBHC_HPHR_PA_OFF_ACK, &mbhc->hph_pa_dac_state);
	} else {
		pr_debug("%s PA is off\n", __func__);
	}
	snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN,
			    0x30, 0x00);
	usleep_range(wg_time * 1000, wg_time * 1000 + 50);
}

static void wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
	uint32_t *zr)
{
@@ -300,6 +361,7 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
			 jack_type, mbhc->hph_status);
		wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
				mbhc->hph_status, WCD_MBHC_JACK_MASK);
		wcd_mbhc_set_and_turnoff_hph_padac(mbhc);
		hphrocp_off_report(mbhc, SND_JACK_OC_HPHR);
		hphlocp_off_report(mbhc, SND_JACK_OC_HPHL);
		mbhc->current_plug = PLUG_TYPE_NONE;
@@ -340,6 +402,7 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
			 jack_type, mbhc->hph_status);
		wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
				    mbhc->hph_status, WCD_MBHC_JACK_MASK);
		wcd_mbhc_clr_and_turnon_hph_padac(mbhc);
	}
	pr_debug("%s: leave hph_status %x\n", __func__, mbhc->hph_status);
}
+8 −0
Original line number Diff line number Diff line
@@ -26,6 +26,11 @@ enum wcd_mbhc_plug_type {
	PLUG_TYPE_GND_MIC_SWAP,
};

enum pa_dac_ack_flags {
	WCD_MBHC_HPHL_PA_OFF_ACK = 0,
	WCD_MBHC_HPHR_PA_OFF_ACK,
};

struct wcd_mbhc_config {
	bool read_fw_bin;
	void *calibration;
@@ -60,6 +65,9 @@ struct wcd_mbhc {

	struct snd_soc_codec *codec;

	/* track PA/DAC state to sync with userspace */
	unsigned long hph_pa_dac_state;

	/* impedance of hphl and hphr */
	uint32_t zl, zr;
	bool impedance_detect;