Skip to content

Instantly share code, notes, and snippets.

@fewtarius
Last active February 10, 2024 20:12
Show Gist options
  • Save fewtarius/f691d97513c4f7e527cb41f44c069548 to your computer and use it in GitHub Desktop.
Save fewtarius/f691d97513c4f7e527cb41f44c069548 to your computer and use it in GitHub Desktop.
Fixing Jack Sense and EAPD

Fixing Jack Sense and EAPD

This mini-guide helps correct issues with internal speakers or the headphone jack outputting static and not functioning after sleep. It deprecates CodecCommander, ALC_JackFix, my JackFix script, and all other combo jack helpers by correcting the layout in AppleALC.

Prerequisites

  • Xcode
  • The latest AppleALC source code tested to build cleanly
  • A Codec Dump from Linux or OpenCore
  • ProperTree

Evaluating the Codec Dump

Issues related to speaker or headphone static, or the headphone jack not switching outputs/inputs tends to be related to EAPD and jack sense being misconfigured in your AppleALC layout. To correct this condition we need to review the codec dump to verify that your codec implementation supports both EAPD (EAPD Detect) on all of your output switches and jack sense (In Detect) on your jack microphone.

EAPD Validation

Review your codec dump to determine that both the internal and headphone output switches support EAPD. Using my codec dump as the example we can see that output switch nodes 0x14 and 0x21 support EAPD (EAPD Detect).

Node 0x14 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out
  Control: name="Speaker Playback Switch", index=0, device=0
    ControlAmp: chs=3, dir=Out, idx=0, ofs=0
  Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1
  Amp-Out vals:  [0x00 0x00]
  Pincap 0x00010014: OUT EAPD Detect
  EAPD 0x2: EAPD
  Pin Default 0x90170110: [Fixed] Speaker at Int N/A
    Conn = Analog, Color = Unknown
    DefAssociation = 0x1, Sequence = 0x0
    Misc = NO_PRESENCE
  Pin-ctls: 0x40: OUT
  Unsolicited: tag=00, enabled=0
  Power states:  D0 D1 D2 D3 EPSS
  Power: setting=D0, actual=D0
  Connection: 1
     0x02
Node 0x21 [Pin Complex] wcaps 0x40058d: Stereo Amp-Out
  Control: name="Headphone Playback Switch", index=0, device=0
    ControlAmp: chs=3, dir=Out, idx=0, ofs=0
  Amp-Out caps: ofs=0x00, nsteps=0x00, stepsize=0x00, mute=1
  Amp-Out vals:  [0x00 0x00]
  Pincap 0x0001001c: OUT HP EAPD Detect
  EAPD 0x2: EAPD
  Pin Default 0x04211020: [Jack] HP Out at Ext Right
    Conn = 1/8, Color = Black
    DefAssociation = 0x2, Sequence = 0x0
  Pin-ctls: 0xc0: OUT HP
  Unsolicited: tag=01, enabled=1
  Power states:  D0 D1 D2 D3 EPSS
  Power: setting=D0, actual=D0
  Connection: 2
     0x02 0x03*

Jack Sense Validation

Repeat evaluating for jack sense. Using my codec dump as the example we can see that the headphone jack microphone at node 0x19 supports jack sense (IN Detect).

Node 0x19 [Pin Complex] wcaps 0x40048b: Stereo Amp-In
  Control: name="Mic Boost Volume", index=0, device=0
    ControlAmp: chs=3, dir=In, idx=0, ofs=0
  Amp-In caps: ofs=0x00, nsteps=0x03, stepsize=0x27, mute=0
  Amp-In vals:  [0x00 0x00]
  Pincap 0x00003724: IN Detect
    Vref caps: HIZ 50 GRD 80 100
  Pin Default 0x04a11040: [Jack] Mic at Ext Right
    Conn = 1/8, Color = Black
    DefAssociation = 0x4, Sequence = 0x0
  Pin-ctls: 0x24: IN VREF_80
  Unsolicited: tag=02, enabled=1
  Power states:  D0 D1 D2 D3 EPSS
  Power: setting=D0, actual=D0

Correcting The Layout

Now that you have the node information, it's time to check your layout in the AppleALC source code, and correct the verbs if necessary. The pin configuration data for all AppleALC layouts is located in the following Info.plist:

AppleALC/Resources/PinConfigs.kext/Contents/Info.plist

To open this plist, browse to AppleALC/Resources. Right click PinConfigs.kext and select Show Package Contents. Open Contents, and then open the Info.plist with ProperTree. Browse the info.plist to find your codec and layout. The configuration data that we will validate and update is stored in the ConfigData and WakeConfigData keys. AppleALC uses the ConfigData key to initialize the codec, and WakeConfigData is sent to the codec after each wake event.

PinConfigs.kext

A Simple PinComplex Primer

Before we continue, we should talk about the pin complex. In the ConfigData and WakeConfigData above, you may notice that there are many 8 bit hexidecimal blocks of data. Each of these blocks of data is a pin complex. They represent configuration data about your codec that AppleALC sends to AppleHDA. You can decode a pin complex like this:

  0  14 70C  02
  │ └┬┘ └┬┘ └┬┘
  │  │   │   │
  │  │   │   │
  │  │   │   │
  │  │   │   └───── Instruction
  │  │   └────── Verb
  │  └─────── Node Location
  └──────── Codec # (Usually 0)

In the example above you can see that AppleALC is sending an instruction of 02 to verb 70C along node 14. Verb 70C is the EAPD enable verb, and instruction 02 is enabling EAPD. Node 14 represents the internal speaker.

For this guide we will be focusing on two verbs, EAPD Enable and Pin Widget Control.

Verb Function Why we need it
70C EAPD Enable Enables the headphone jack switch
707 Pin Widget Control Enables jack sense

You can read about these verbs, and other configuration verbs in the Intel HDA specification manual.

Validating the Layout

As we can see above that after a wake, the EAPD enable verb is being enabled on the internal speaker, but not to the headphone jack. Let's look at the data to see exactly what's happening.

ConfigData

Since we know that the EAPD Enable verb is 70C, we can see below that it is only being sent to node 0x14. This will need to be corrected to also send the verb to node 0x21. We do not need to send a pin widget control verb to our output devices.

01471C10 01471D01 01471E13 01471F99 01470C02 02171C20 02171D10 02171E21 02171F13 01971C40 01971D11 01971EA1 01971F93

WakeConfigData

Evaluating the data below we learn that as during codec initialization, the EAPD enable verb is only being sent to node 0x14. This will also need to be corrected to send the EAPD enable verb to node 0x21. Additionally, the pin widget control verb is missing and will need to be added. The instruction we will send to the pin widget control verb is 25.

01470C02

Correcting the Layout

Now that we have determined what we need to correct in our layout data, let's correct it. Using the pin complex breakdown above, create new pin complexes for your layout and add them to the appropriate keys under your codec and layout.

ConfigData

01471C10 01471D01 01471E13 01471F99 01470C02 02171C20 02171D10 02171E21 02171F13 02170C02 01971C40 01971D11 01971EA1 01971F93

WakeConfigData

01470C02 02170C02 01970725

PinConfigs.kext

Testing the Corrected Layout

Now that you've corrected the layout, it's time to build AppleALC and test it. Be sure to remove VerbStub, CodecCommander, ALCWakeFix, ComboJack, ALC Plug Fix, JackFix, and any other helper that may be installed as those helpers can clobber the fix. If you've successfully corrected the layout, let it soak for a few days of use and then consider submitting the fix to AppleALC as a pull request.

@chaojiacheng
Copy link

This guide helps me a lot. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment