It’s only been a few weeks since we last talked about Librem-EC, but here we are again!  This time instead of power management, we’re looking at the headset jack, which had two longstanding issues.  Although headphones worked, the jack detect did not, so you had to select the output manually.  Microphone input has never worked.

Yes, We’re (Normally) Open

How does the OS know when a headset is plugged in?  This is a physical jack, so there must be a physical change that is detectable.

Some jacks have normally-closed sense pins that open when you insert a plug.  These might be readable as a simple digital I/O – high or low.  If you’ve ever wired gadgets onto the GPIO pins of a Raspberry Pi, it’s something like that.

The Librem 14, though, has a normally open sense pin.  The plug tip shorts two pins together.  The jack’s datasheet has a diagram worth a thousand words:

Librem 14 jack schematic. Pins 4 and 5 both touch the plug tip.

See how pin 4 and 5 both touch the tip?  One of these will just have the left audio signal on it.  The other is the sense – either it reads “open” or “left audio signal”.  It’s not a clean digital input – this was the first problem.

Analog Sense

Because the sense pin isn’t a clean digital signal, the EC has to use its analog-to-digital converter to measure the sense level, then decide whether a plug is inserted.

The digital logic actually worked some of the time.  Most of the time, if the signal was quiet, the EC still noticed the plug in event.  Testing this properly required cranking up the volume of some very loud music.  My office sounded like a Nickelback concert for a little while, but this confirmed that analog sense worked reliably.

Enter the Codec

This improved the jack detection by the EC, and I reverted the audio verbs in coreboot to re-enable the jack sense.  (We had disabled it as a workaround so you could manually select the jack.)  The codec still did not report the plug events though.

After the EC notices a plug insertion, it has to inform the codec.  That’s the Realtek ALC256 audio codec, and for whatever reason, Realtek is very secretive about what it does and how we configure it.  While we were able to get a datasheet for the ALC256, it documents little beyond the HDA verbs, which the hda-verb tool already understands.  The actual meaning of the “pin configuration” in those verbs, the codec parameters, and the most of the sense behavior is undocumented.

The codec seemed to simply ignore the signal from the EC, and we could not tell why.  The connection between the EC and codec is complex, but it boils down to something like this:

Sample schematic showing codec and EC connections. Codec GPIO2 and EC GPF0 are connected. A resistor connects them to +3.3V.

I cleaned out a lot from the real schematic here, but it’s pretty clearly an open-drain signal.  The EC, codec, and digital microphone could pull down the signal to signal ‘low’, or leave it alone to signal ‘high’ – the resistor pulls it up by default.  (That’s called “tri-stating,” meaning we don’t drive the signal high or low, we set it to “high impedance,” the third state.)  Nobody pushes it high.

Except – this was wrong.  We got a tip that the EC actually does need to drive the signal high to trigger the jack sense in the codec.  I thought this made no sense, but I could also see that when the EC tristated the signal, the signal was not going high.  Something was still holding it low.  I removed the digital microphone, which confirmed that the codec was still holding it low.

So I tried it – have the EC push high anyway, despite what it looked like.  And it worked!  Suddenly it could detect both headphones and mic.  Evidently the codec is designed for this, it seem to weakly pull the signal low expecting that it could be actively driven high in this situation.

With some testing input from a few others, we found that the codec was happy as long as the EC pushed the line high for about 10 ms following a jack plug, then we can tri-state it.  I can only speculate, but I suspect that the codec changes the pin over from digital microphone to GPIO2 as a result of this signal, and it appears to test whether there is actually a microphone present.  The codec can tell the difference between plain headphones and a headset with mic in the jack.

Backward Compatibility

With the jack detect working in the EC and codec, we just needed to revert the verbs in coreboot to enable the jack detect.

Coreboot still falls back to the old verbs if the EC hasn’t been updated yet.  That way, manual headphone selection still works if a newer coreboot runs with an older EC.  To do this, coreboot queries the EC during boot.  EC 1.13 adds a flag indicating that the jack sense works, so coreboot can use the updated verbs.

The EC change is released in Librem-EC 1.13.  As always, update with our update instructions and check out the source!  The updated HDA verbs will be in coreboot 4.19-Purism-1 and PureBoot 25, which we will release soon!


Purism Products and Availability Chart

 ModelStatusLead Time 
USB Security Token Purism Librem KeyLibrem Key

(Made in USA)
In Stock
20 business days
Librem 5In Stock
10 business days
Librem 5 COMSEC BundleIn Stock
Qty 2; 3GB/32GB
10 business days
Librem 5 + SIMple
(3 GB Data)
In Stock
10 business days
Librem 5 + SIMple Plus
(5 GB Data)
In Stock
10 business days
Librem 5 + AweSIM
(Unlimited Data)
In Stock
10 business days
Librem 11In Stock
45 business days
Most Secure Laptop Purism Librem 14Librem 14In Stock
20 business days
Most Secure PC Purism Librem Mini
Librem MiniJune 2024
45 business days
Purism Liberty Phone with Made in USA ElectronicsLiberty Phone
(Made in USA Electronics)
June 2024
20 business days
Most Secure Server Purism Librem ServersLibrem ServerJune 2024
60 business days
The current product and shipping chart of Purism Librem products, updated on April 30th, 2024

Recent Posts

Related Content