alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
From: Hans de Goede <hdegoede@redhat.com>
To: Mark Brown <broonie@kernel.org>, Bard Liao <bardliao@realtek.com>,
	Oder Chiou <oder_chiou@realtek.com>,
	Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Cc: Hans de Goede <hdegoede@redhat.com>,
	alsa-devel@alsa-project.org, Carlo Caione <carlo@endlessm.com>,
	Takashi Iwai <tiwai@suse.com>
Subject: [PATCH v3 09/22] ASoC: rt5651: Rewrite jack-type detection
Date: Sun,  4 Mar 2018 15:35:57 +0100	[thread overview]
Message-ID: <20180304143610.21125-10-hdegoede@redhat.com> (raw)
In-Reply-To: <20180304143610.21125-1-hdegoede@redhat.com>

We get the insertion event before the jack is fully inserted at which point
the second ring on a TRRS connector may short the 2nd ring and sleeve
contacts. Testing has shown that this short-circuit may happen as late
as 500ms after the insertion event, but it never lasts longer then 300ms.

This commit changes the detection algorithm to require 5 identical OVCD
values in a row at 100 ms intervals to fix the jack-type sometimes getting
mis-detected.

Tested-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 sound/soc/codecs/rt5651.c | 110 +++++++++++++++++++++++++++++-----------------
 sound/soc/codecs/rt5651.h |   2 +-
 2 files changed, 70 insertions(+), 42 deletions(-)

diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 3870c0f3b30f..6b5669f3e85d 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -1622,12 +1622,76 @@ static bool rt5651_jack_inserted(struct snd_soc_component *component)
 	return val == 0;
 }
 
+/* Jack detect timings */
+#define JACK_SETTLE_TIME	100 /* milli seconds */
+#define JACK_DETECT_COUNT	5
+#define JACK_DETECT_MAXCOUNT	20  /* Aprox. 2 seconds worth of tries */
+
+static int rt5651_detect_headset(struct snd_soc_component *component)
+{
+	int i, headset_count = 0, headphone_count = 0;
+
+	/*
+	 * We get the insertion event before the jack is fully inserted at which
+	 * point the second ring on a TRRS connector may short the 2nd ring and
+	 * sleeve contacts, also the overcurrent detection is not entirely
+	 * reliable. So we try several times with a wait in between until we
+	 * detect the same type JACK_DETECT_COUNT times in a row.
+	 */
+	for (i = 0; i < JACK_DETECT_MAXCOUNT; i++) {
+		/* Clear any previous over-current status flag */
+		rt5651_clear_micbias1_ovcd(component);
+
+		msleep(JACK_SETTLE_TIME);
+
+		/* Check the jack is still connected before checking ovcd */
+		if (!rt5651_jack_inserted(component))
+			return 0;
+
+		if (rt5651_micbias1_ovcd(component)) {
+			/*
+			 * Over current detected, there is a short between the
+			 * 2nd ring contact and the ground, so a TRS connector
+			 * without a mic contact and thus plain headphones.
+			 */
+			dev_dbg(component->dev, "mic-gnd shorted\n");
+			headset_count = 0;
+			headphone_count++;
+			if (headphone_count == JACK_DETECT_COUNT)
+				return SND_JACK_HEADPHONE;
+		} else {
+			dev_dbg(component->dev, "mic-gnd open\n");
+			headphone_count = 0;
+			headset_count++;
+			if (headset_count == JACK_DETECT_COUNT)
+				return SND_JACK_HEADSET;
+		}
+	}
+
+	dev_err(component->dev, "Error detecting headset vs headphones, bad contact?, assuming headphones\n");
+	return SND_JACK_HEADPHONE;
+}
+
+static void rt5651_jack_detect_work(struct work_struct *work)
+{
+	struct rt5651_priv *rt5651 =
+		container_of(work, struct rt5651_priv, jack_detect_work);
+	int report = 0;
+
+	if (rt5651_jack_inserted(rt5651->component)) {
+		rt5651_enable_micbias1_for_ovcd(rt5651->component);
+		report = rt5651_detect_headset(rt5651->component);
+		rt5651_disable_micbias1_for_ovcd(rt5651->component);
+	}
+
+	snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
+}
+
 static irqreturn_t rt5651_irq(int irq, void *data)
 {
 	struct rt5651_priv *rt5651 = data;
 
-	queue_delayed_work(system_power_efficient_wq,
-			   &rt5651->jack_detect_work, msecs_to_jiffies(250));
+	queue_work(system_power_efficient_wq, &rt5651->jack_detect_work);
 
 	return IRQ_HANDLED;
 }
@@ -1715,8 +1779,7 @@ static int rt5651_set_jack(struct snd_soc_component *component,
 	}
 
 	/* sync initial jack state */
-	queue_delayed_work(system_power_efficient_wq,
-			   &rt5651->jack_detect_work, 0);
+	queue_work(system_power_efficient_wq, &rt5651->jack_detect_work);
 
 	return 0;
 }
@@ -1929,41 +1992,6 @@ static const struct i2c_device_id rt5651_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id);
 
-static int rt5651_jack_detect(struct snd_soc_component *component, int jack_insert)
-{
-	int jack_type;
-
-	if (jack_insert) {
-		rt5651_enable_micbias1_for_ovcd(component);
-		rt5651_clear_micbias1_ovcd(component);
-		msleep(100);
-		if (rt5651_micbias1_ovcd(component))
-			jack_type = SND_JACK_HEADPHONE;
-		else
-			jack_type = SND_JACK_HEADSET;
-		rt5651_disable_micbias1_for_ovcd(component);
-	} else { /* jack out */
-		jack_type = 0;
-	}
-
-	return jack_type;
-}
-
-static void rt5651_jack_detect_work(struct work_struct *work)
-{
-	struct rt5651_priv *rt5651 =
-		container_of(work, struct rt5651_priv, jack_detect_work.work);
-	int report, jack_inserted;
-
-	if (!rt5651->component)
-		return;
-
-	jack_inserted = rt5651_jack_inserted(rt5651->component);
-	report = rt5651_jack_detect(rt5651->component, jack_inserted);
-
-	snd_soc_jack_report(rt5651->hp_jack, report, SND_JACK_HEADSET);
-}
-
 /*
  * Note this function MUST not look at device-properties, see the comment
  * above rt5651_apply_properties().
@@ -2006,7 +2034,7 @@ static int rt5651_i2c_probe(struct i2c_client *i2c,
 	rt5651->irq = i2c->irq;
 	rt5651->hp_mute = 1;
 
-	INIT_DELAYED_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work);
+	INIT_WORK(&rt5651->jack_detect_work, rt5651_jack_detect_work);
 
 	ret = devm_snd_soc_register_component(&i2c->dev,
 				&soc_component_dev_rt5651,
@@ -2019,7 +2047,7 @@ static int rt5651_i2c_remove(struct i2c_client *i2c)
 {
 	struct rt5651_priv *rt5651 = i2c_get_clientdata(i2c);
 
-	cancel_delayed_work_sync(&rt5651->jack_detect_work);
+	cancel_work_sync(&rt5651->jack_detect_work);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h
index 71738ab93fb9..f20c9be94fb2 100644
--- a/sound/soc/codecs/rt5651.h
+++ b/sound/soc/codecs/rt5651.h
@@ -2072,7 +2072,7 @@ struct rt5651_priv {
 	struct snd_soc_component *component;
 	struct regmap *regmap;
 	struct snd_soc_jack *hp_jack;
-	struct delayed_work jack_detect_work;
+	struct work_struct jack_detect_work;
 	enum rt5651_jd_src jd_src;
 	unsigned int ovcd_th;
 	unsigned int ovcd_sf;
-- 
2.14.3

  parent reply	other threads:[~2018-03-04 14:36 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-03-04 14:35 [PATCH v3 00/22] ASoC: rt5651: jack-detect fixes and improvements Hans de Goede
2018-03-04 14:35 ` [PATCH v3 01/22] ASoC: rt5651: Make rt5651_apply_properties() private Hans de Goede
2018-03-07 14:14   ` Applied "ASoC: rt5651: Make rt5651_apply_properties() private" to the asoc tree Mark Brown
2018-03-04 14:35 ` [PATCH v3 02/22] ASoC: rt5651: Add devicetree-bindings for jack-detect Hans de Goede
2018-03-07 14:14   ` Applied "ASoC: rt5651: Add devicetree-bindings for jack-detect" to the asoc tree Mark Brown
2018-03-04 14:35 ` [PATCH v3 03/22] ASoC: rt5651: Configure jack-detect source through a device-property Hans de Goede
2018-03-07 12:34   ` Mark Brown
2018-03-07 13:49     ` Hans de Goede
2018-03-07 14:28       ` Mark Brown
2018-03-07 14:14   ` Applied "ASoC: rt5651: Configure jack-detect source through a device-property" to the asoc tree Mark Brown
2018-03-04 14:35 ` [PATCH v3 04/22] ASoC: rt5651: Allow specifying over-current threshold through a device-property Hans de Goede
2018-03-07 14:14   ` Applied "ASoC: rt5651: Allow specifying over-current threshold through a device-property" to the asoc tree Mark Brown
2018-03-04 14:35 ` [PATCH v3 05/22] ASoC: rt5651: Allow specifying the OVCD scale-factor through a device-property Hans de Goede
2018-03-07 14:14   ` Applied "ASoC: rt5651: Allow specifying the OVCD scale-factor through a device-property" to the asoc tree Mark Brown
2018-03-04 14:35 ` [PATCH v3 06/22] ASoC: rt5651: Enable sticky mode for OVCD Hans de Goede
2018-03-04 14:35 ` [PATCH v3 07/22] ASoC: rt5651: Enable Platform Clock during jack-type detect Hans de Goede
2018-03-04 14:35 ` [PATCH v3 08/22] ASoC: rt5651: Add rt5651_jack_inserted() helper Hans de Goede
2018-03-04 14:35 ` Hans de Goede [this message]
2018-03-07 14:13   ` Applied "ASoC: rt5651: Rewrite jack-type detection" to the asoc tree Mark Brown
2018-03-04 14:35 ` [PATCH v3 10/22] ASoC: Intel: bytcr_rt5651: Not being able to find the codec ACPI-dev is an error Hans de Goede
2018-03-07 14:13   ` Applied "ASoC: Intel: bytcr_rt5651: Not being able to find the codec ACPI-dev is an error" to the asoc tree Mark Brown
2018-03-04 14:35 ` [PATCH v3 11/22] ASoC: Intel: bytcr_rt5651: Pass jack-src info via device-properties Hans de Goede
2018-03-07 14:22   ` Applied "ASoC: Intel: bytcr_rt5651: Pass jack-src info via device-properties" to the asoc tree Mark Brown
2018-03-04 14:36 ` [PATCH v3 12/22] ASoC: Intel: bytcr_rt5651: Actually honor the DMIC_EN quirk if specified Hans de Goede
2018-03-07 14:22   ` Applied "ASoC: Intel: bytcr_rt5651: Actually honor the DMIC_EN quirk if specified" to the asoc tree Mark Brown
2018-03-04 14:36 ` [PATCH v3 13/22] ASoC: Intel: bytcr_rt5651: Only create jack if we have a jack-detect source Hans de Goede
2018-03-07 14:22   ` Applied "ASoC: Intel: bytcr_rt5651: Only create jack if we have a jack-detect source" to the asoc tree Mark Brown
2018-03-04 14:36 ` [PATCH v3 14/22] ASoC: Intel: bytcr_rt5651: Add quirk micbias OVCD configuration Hans de Goede
2018-03-07 14:22   ` Applied "ASoC: Intel: bytcr_rt5651: Add quirk micbias OVCD configuration" to the asoc tree Mark Brown
2018-03-04 14:36 ` [PATCH v3 15/22] ASoC: Intel: bytcr_rt5651: Configure PLL1 before using it Hans de Goede
2018-03-04 14:36 ` [PATCH v3 16/22] ASoC: Intel: bytcr_rt5651: Drop snd_soc_dai_set_bclk_ratio() call Hans de Goede
2018-03-04 14:36 ` [PATCH v3 17/22] ASoC: Intel: bytcr_rt5651: Rename IN3_MAP to IN1_HS_IN3_MAP Hans de Goede
2018-03-04 14:36 ` [PATCH v3 18/22] ASoC: Intel: bytcr_rt5651: Add new IN2_HS_IN3 input map and a quirk using it Hans de Goede
2018-03-04 14:36 ` [PATCH v3 19/22] ASoC: Intel: bytcr_rt5651: Add support for Bay Trail CR / SSP0 using boards Hans de Goede
2018-03-07 14:21   ` Applied "ASoC: Intel: bytcr_rt5651: Add support for Bay Trail CR / SSP0 using boards" to the asoc tree Mark Brown
2018-03-09 23:30   ` [PATCH v3 19/22] ASoC: Intel: bytcr_rt5651: Add support for Bay Trail CR / SSP0 using boards Pierre-Louis Bossart
2018-03-11 18:19     ` Hans de Goede
2018-03-12 23:26       ` Pierre-Louis Bossart
2018-03-04 14:36 ` [PATCH v3 20/22] ASoC: Intel: bytcr_rt5651: Add quirk for the VIOS LTH17 laptop Hans de Goede
2018-03-04 14:36 ` [PATCH v3 21/22] ASoC: Intel: bytcr_rt5651: Change defaults to enable jack-detect, analog mics Hans de Goede
2018-03-04 14:36 ` [PATCH v3 22/22] ASoC: Intel: bytcr_rt5651: Select RCCLK on init() Hans de Goede

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180304143610.21125-10-hdegoede@redhat.com \
    --to=hdegoede@redhat.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=bardliao@realtek.com \
    --cc=broonie@kernel.org \
    --cc=carlo@endlessm.com \
    --cc=oder_chiou@realtek.com \
    --cc=pierre-louis.bossart@linux.intel.com \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).