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

Commit fc600205 authored by Walter Yang's avatar Walter Yang
Browse files

ASoC: wcd: Add polling for proper headphone detection



When we insert headphone slowly, it may be detected as HEADSET
incorrectly.
So when we detect the HEADSET type, report it first and then schedule
the polling for it. If then button press interrupt is triggered
without corresponding button release paired, correct it to headphone.

CRs-Fixed: 678536
Change-Id: I82a043bf3ccccd956a79b9a96d393a9c0f46e8da
Signed-off-by: default avatarWalter Yang <yandongy@codeaurora.org>
parent d81481d4
Loading
Loading
Loading
Loading
+28 −6
Original line number Diff line number Diff line
@@ -476,6 +476,11 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
			mbhc->hph_status &= ~(SND_JACK_HEADSET |
						SND_JACK_LINEOUT);
		}

		if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET &&
			jack_type == SND_JACK_HEADPHONE)
			mbhc->hph_status &= ~SND_JACK_HEADSET;

		/* Report insertion */
		mbhc->hph_status |= jack_type;

@@ -513,8 +518,7 @@ static void wcd_mbhc_find_plug_and_report(struct wcd_mbhc *mbhc,

	WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);

	if (plug_type == MBHC_PLUG_TYPE_HEADPHONE &&
	    mbhc->current_plug == MBHC_PLUG_TYPE_NONE) {
	if (plug_type == MBHC_PLUG_TYPE_HEADPHONE) {
		/*
		 * Nothing was reported previously
		 * report a headphone or unsupported
@@ -599,13 +603,23 @@ static void wcd_correct_swch_plug(struct work_struct *work)
		} else {
			pr_debug("%s: cable is headset\n", __func__);
			plug_type = MBHC_PLUG_TYPE_HEADSET;
			if (mbhc->current_plug != MBHC_PLUG_TYPE_HEADSET) {
				wcd_mbhc_find_plug_and_report(mbhc, plug_type);
				return;
			}
			wrk_complete = false;
		}
	}
	if (wrk_complete == true)
		plug_type = MBHC_PLUG_TYPE_HIGH_HPH;
	else
	else if (plug_type == MBHC_PLUG_TYPE_HEADSET) {
		if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET &&
			mbhc->btn_press_intr) {
			pr_debug("%s: Can be slow insertion of headphone\n",
				__func__);
			plug_type = MBHC_PLUG_TYPE_HEADPHONE;
		}
	} else
		plug_type = MBHC_PLUG_TYPE_INVALID;

	if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH) {
@@ -790,9 +804,13 @@ eu_us_switch:
	pr_debug("%s: Valid plug found, plug type is %d\n",
			 __func__, plug_type);
	if (plug_type != MBHC_PLUG_TYPE_HIGH_HPH &&
			plug_type != MBHC_PLUG_TYPE_HEADSET &&
			plug_type != MBHC_PLUG_TYPE_INVALID)
		wcd_mbhc_find_plug_and_report(mbhc, plug_type);
	else
	else if (plug_type == MBHC_PLUG_TYPE_HEADSET) {
		wcd_mbhc_find_plug_and_report(mbhc, plug_type);
		wcd_schedule_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
	} else
		wcd_schedule_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
exit:
	pr_debug("%s: leave\n", __func__);
@@ -858,6 +876,7 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
				    0x30, 0x00);
		if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) {
			wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADPHONE);
			mbhc->btn_press_intr = false;
		} else if (mbhc->current_plug == MBHC_PLUG_TYPE_GND_MIC_SWAP) {
			wcd_mbhc_report_plug(mbhc, 0, SND_JACK_UNSUPPORTED);
		} else if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET) {
@@ -996,6 +1015,7 @@ irqreturn_t wcd_mbhc_btn_press_handler(int irq, void *data)
	/* send event to sw intr handler*/
	mbhc->is_btn_press = true;
	wake_up_interruptible(&mbhc->wait_btn_press);
	mbhc->btn_press_intr = true;

	msec_val = jiffies_to_msecs(jiffies - mbhc->jiffies_atreport);
	pr_debug("%s: msec_val = %ld\n", __func__, msec_val);
@@ -1035,6 +1055,7 @@ static irqreturn_t wcd_mbhc_release_handler(int irq, void *data)

	pr_debug("%s: enter\n", __func__);
	WCD_MBHC_RSC_LOCK(mbhc);
	mbhc->btn_press_intr = false;

	/*
	 * If current plug is headphone then there is no chance to
@@ -1227,6 +1248,7 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec,
	mbhc->gnd_swh = gnd_swh;
	mbhc->micbias_enable = false;
	mbhc->mbhc_cb = mbhc_cb;
	mbhc->btn_press_intr = false;

	if (mbhc->intr_ids == NULL) {
		pr_err("%s: Interrupt mapping not provided\n", __func__);
+1 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ struct wcd_mbhc {
	bool gnd_swh; /*track GND switch NC / NO */
	bool hs_detect_work_stop;
	bool micbias_enable;
	bool btn_press_intr;

	struct snd_soc_codec *codec;