[Gta04-owner] Headset detection.

NeilBrown neilb at suse.de
Sat Aug 25 00:49:24 CEST 2012


On Wed, 22 Aug 2012 11:08:43 +1000 NeilBrown <neilb at suse.de> wrote:

> On Tue, 21 Aug 2012 12:30:47 +0200 "Dr. H. Nikolaus Schaller"
> <hns at goldelico.com> wrote:
> 
> > Hi Neil,
> > 
> > Am 18.08.2012 um 02:13 schrieb NeilBrown:

> > 
> > > I don't suppose there is an existing standard....
> > 
> > Not really.
> > 
> > Generally you can only say:
> > short on Mic = green phone key (answer call on headset)
> > some kOhm on Mic = there is a Mic
> > high Z = there is no Mic
> 
> So 'short on Mic' cannot be distinguished from a 3-contact headset (no
> microphone, 'shield' is larger and shorts together 'shield' and 'ring-1').
> I guess  a transition from 'some kOhm' to 'short-on-Mic' means the button was
> pressed, where as a transition from 'high Z' to 'short on Mic' means a
> 3-contact headset was plugged in.
> 
> Also if we want button presses to work well I probably need to increase the
> poll rate when something is plugged in.
> 
> I don't have a working 2.5mm headset, or a working 3.5-2.5 4-contact
> converter so I cannot experiment very much.
> I'll see if I can get hold of one...

I got hold of one (next day delivery! I was impressed :-)

The following patch which I have committed detects whether a mic is present
or not, and can detect a button which shorts the mic line.

I'm perplexed by the numbers though.
- open circuit (nothing plugged in) gives a very low reading (20) - negligible
  current flowing.  That makes sense.
- closed circuit (3-pin connector or button pressed) gives a high readings,
  (800ish).  Max current allowed by internal resistors is flowing.  That also
  makes sense.
- mic present gives an *even*higher* reading!!  830 to 850.  What could cause
  that?  How can the mic cause more current to flow?  I thought there might be
  leakage from the headphone driver but I couldn't measure any.

> 
> If someone else wants to experiment, just report the values that appear in 
>     /sys/class/hwmon/hwmon0/device/in7_input
> when different events happen with some headset (with my any kernel which
> enables this driver, just as my 3.5 branch).

Note that you need to have /dev/input/jack open (e.g. evtest /dev/input/jack)
for these readings to be valid.


Finally: while I can play music through my headset with no trouble, the mic
doesn't work very well - I can hear what I say but it is very very quiet.
Has anyone else tried with a head-set microphone?  Any luck?
Among the things I tried was 
   alsactl -f  /opt/qtmoko/etc/alsa/gsmheadset.state  restore

This is weird  - when I play music I hear it coming from the earpiece even
though that is muted.   When I unmute the earpiece it keeps playing.  When I
mute again it goes silent.  Something must be wrong in the driver.

NeilBrown


commit 169e831d949b83f7b7bb536b9b5009468af98cd2
Author: NeilBrown <neilb at suse.de>
Date:   Sat Aug 25 08:44:51 2012 +1000

    GTA04 audio headset jack detect.
    
    Enhance jack detection to differentiate with and without a microphone,
    and to report a button-press when the microphone is shorted.
    
    Signed-off-by: NeilBrown <neilb at suse.de>

diff --git a/GTA04/udev-rules/input.rules b/GTA04/udev-rules/input.rules
index a96feb8..2cc8df9 100644
--- a/GTA04/udev-rules/input.rules
+++ b/GTA04/udev-rules/input.rules
@@ -4,4 +4,4 @@ SUBSYSTEM=="input", KERNEL=="event[0-9]*", ATTRS{modalias}=="input:*-e0,3,*a0,1,
 SUBSYSTEM=="input", KERNEL=="event[0-9]*", ATTRS{modalias}=="input:*-e0,1,*k74,*", SYMLINK+="input/power"
 SUBSYSTEM=="input", KERNEL=="event[0-9]*", ATTRS{modalias}=="input:*-e0,1,*kA9,*", SYMLINK+="input/aux"
 SUBSYSTEM=="input", KERNEL=="event[0-9]*", ATTRS{modalias}=="input:*-e0,1,*kF0,*", SYMLINK+="input/incoming"
-SUBSYSTEM=="input", KERNEL=="event[0-9]*", ATTRS{modalias}=="input:*-e0,5,*w[24678D]*", SYMLINK+="input/jack"
+SUBSYSTEM=="input", KERNEL=="event[0-9]*", ATTRS{modalias}=="input:*-e0*,5,*w[24678D]*", SYMLINK+="input/jack"
diff --git a/sound/soc/omap/gta04-audio.c b/sound/soc/omap/gta04-audio.c
index 1048098..804bce9 100644
--- a/sound/soc/omap/gta04-audio.c
+++ b/sound/soc/omap/gta04-audio.c
@@ -145,20 +145,63 @@ static struct {
 	struct delayed_work jack_work;
 	struct snd_soc_codec *codec;
 	int open;
+	/* When any jack is present, we:
+	 * - poll more quickly to catch button presses
+	 * - assume a 'short' is 'button press', not 'headset has
+	 *   no mic
+	 * 'present' stores SND_JACK_HEADPHONE and SND_JACK_MICROPHONE
+	 * indication what we thing is present.
+	 */
+	int present;
 } jack;
 
 static void gta04_audio_jack_work(struct work_struct *work)
 {
 	long val;
+	long delay = msecs_to_jiffies(500);
+	int jackbits;
+
+	/* choose delay *before* checking presence so we still get
+	 * one long delay on first insertion to help with debounce.
+	 */
+	if (jack.present)
+		delay = msecs_to_jiffies(50);
 
 	val = twl4030_get_madc_conversion(7);
-	if (val < 100)
-		snd_soc_jack_report(&jack.hs_jack, 0, SND_JACK_HEADSET);
-	else
-		snd_soc_jack_report(&jack.hs_jack, SND_JACK_HEADSET,
-				     SND_JACK_HEADSET);
+	/* On my device:
+	 * open circuit = around 20
+	 * short circuit = around 800
+	 * microphone   = around 830-840 !!!
+	 */
+	if (val < 100) {
+		/* open circuit */
+		jackbits = 0;
+		jack.present = 0;
+		/* debounce */
+		delay = msecs_to_jiffies(500);
+	} else if (val < 820) {
+		/* short */
+		if (jack.present == 0) {
+			/* Inserted headset with no mic */
+			jack.present = SND_JACK_HEADPHONE;
+			jackbits = jack.present;
+		} else if (jack.present & SND_JACK_MICROPHONE) {
+			/* mic shorter == button press */
+			jackbits = SND_JACK_BTN_0 | jack.present;
+		} else {
+			/* headphones still present */
+			jackbits = jack.present;
+		}
+	} else {
+		/* There is a microphone there */
+		jack.present = SND_JACK_HEADSET;
+		jackbits = jack.present;
+	}
+	snd_soc_jack_report(&jack.hs_jack, jackbits,
+			    SND_JACK_HEADSET | SND_JACK_BTN_0);
+
 	if (jack.open)
-		schedule_delayed_work(&jack.jack_work, msecs_to_jiffies(500));
+		schedule_delayed_work(&jack.jack_work, delay);
 }
 
 static int gta04_audio_suspend(struct snd_soc_card *card)
@@ -237,7 +280,8 @@ static int omap3gta04_init(struct snd_soc_pcm_runtime *runtime)
 	 * but we need to poll :-(
 	 */
 	ret = snd_soc_jack_new(codec, "Headset Jack",
-			       SND_JACK_HEADSET, &jack.hs_jack);
+			       SND_JACK_HEADSET | SND_JACK_BTN_0,
+			       &jack.hs_jack);
 	if (ret)
 		return ret;
 	INIT_DELAYED_WORK(&jack.jack_work, gta04_audio_jack_work);


NeilBrown
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 828 bytes
Desc: not available
URL: <http://lists.goldelico.com/pipermail/gta04-owner/attachments/20120825/9ef7888e/attachment-0001.bin>


More information about the Gta04-owner mailing list