Repository navigation
# 3.5mm headphone jack never auto-detects on KONKR Pocket FIT (SM8650) #426
Description
Hardware Device
KONKR Pocket FIT (G3 Gen 3)
OS Version
20260907.78958ee
Description
Hello as you will probably immediately be able to tell I used Claude Code to work through this issue. Apologies if you don't accept help from these tools I had a look around but couldn't see anything forbidding it. I appriciated that this will probably make you treat the below with suspicion but I promise that this is from a place of wanting to help my fellow handheld gamers
We were able to get sound out the device, and I've tested the parts I am able to so as not to waste anyones time.
3.5mm headphone jack never auto-detects on KONKR Pocket FIT (SM8650)
Summary
On the KONKR Pocket FIT (SM8650 / G3 Gen 3), inserting a 3.5mm plug is never detected,
so audio never moves to the headphones. Speakers work normally.
The analog headphone path is fully functional, and the Headphones output is
present and usable — it just has to be selected by hand, because nothing ever reports
the plug. Two independent bugs each break automatic switching:
- Kernel: WCD939x MBHC mechanical insertion detection fires correctly, but
electrical plug-type detection never runs, so the jack control never reports
present. - Userspace (Armada's UCM2 profile): the
Headphonesdevice declares
JackControl "Headset Jack", which is not a control that exists on this card, so
the port's availability can never be evaluated at all.
Either one alone is sufficient to prevent auto-switching. Neither prevents manual
selection.
Workaround for users, no file changes needed:
pactl set-card-profile alsa_card.platform-sound "HiFi (Headphones, Speaker)"
wpctl set-default <headphones-node-id>(wpctl set-default rather than pactl set-default-sink — only the former persists the
choice to ~/.local/state/wireplumber/default-nodes. The profile itself persists via
default-profile either way.) Once the Headphones profile is active, Speaker is also
present in it, so switching between the two outputs afterwards needs no further profile
change. You must switch manually every time; there is no auto-switch.
No Steam restart is required for this workaround — verified on a live
gamescope/gamepadui session (see "Behaviour on a Steam session" below).
Since the switch has to be made by hand every time, it is far more usable wired up as
two non-Steam library shortcuts — see "Practical stopgap" below for the script and the
shortcuts.vdf gotchas.
Affected system
| Device | KONKR Pocket FIT |
| DT compatible | konkr,pocket-fit, qcom,sm8650 |
| SoC | SM8650 (Snapdragon G3 Gen 3) |
| ALSA card | SM8650-APS2 (AYANEO Pocket S2 profile) |
| Machine driver | snd_soc_sc8280xp |
| Image | ghcr.io/armada-os/armada:beta |
| Image version | 20260907.78958ee (sha256:0045126954a1…) |
| Kernel | 7.2.3 aarch64 |
| Fedora base | 44 |
| PipeWire | 1.6.8 |
| WirePlumber | 0.5.14 |
| alsa-lib | 1.2.16.1-1.fc44 |
Note: the board matches the AYANEO Pocket S2 UCM profile and reports itself as
"AYANEO Controller" / "AYANEO DEVICE" in /proc/bus/input/devices. There is no KONKR
profile for sm8650, although conf.d/sm8750/SM8750-KONKR.conf exists for the 8 Elite
variant.
Symptom
- Inserting or removing a 3.5mm plug produces no reaction of any kind: no UI change,
no port switch, no log line, no input event. - Audio keeps going to the speakers.
- Selecting the
Headphonesprofile by hand works and produces correct stereo audio. - Separately, no capture devices are exposed at all (see "Additional issue").
Default card state on boot:
Active Profile: HiFi (HDMI0, Speaker)
$ pactl list sinks short
51 alsa_output.platform-sound.HiFi__HDMI0__sink PipeWire s16le 2ch 48000Hz SUSPENDED
52 alsa_output.platform-sound.HiFi__Speaker__sink PipeWire s16le 2ch 48000Hz SUSPENDED
Headphones conflicts with HDMI0 (both are hw:0,0, and HDMI0 declares
ConflictingDevice ["Headphones"]), so they appear as two mutually exclusive card
profiles rather than two ports of one profile. The card boots into
HiFi (HDMI0, Speaker) and, because jack detection never fires, nothing ever moves it
to HiFi (Headphones, Speaker).
Bug 1 — WCD939x MBHC: mechanical detect fires, electrical detect never runs
Evidence
The MBHC mechanical-detect interrupt works perfectly. Across four physical plug
transitions (unplug, replug, unplug, replug) the counter incremented exactly four
times, one per transition:
# before
246: 6 ... wcd939x 4 Edge mbhc sw intr
# after 4 transitions
246: 10 ... wcd939x 4 Edge mbhc sw intr
But the electrical-detection interrupts never fire at all, at any point:
$ grep -E "Elect Insert|Elect Remove|Button Press" /proc/interrupts
249: 0 ... wcd939x 3 Edge Elect Insert
250: 0 ... wcd939x 2 Edge Elect Remove
247: 0 ... wcd939x 0 Edge Button Press detect
Consequently the plug is never reported. With headphones physically inserted:
$ amixer -c 0 cget numid=139 # 'Headphone Jack'
: values=off
$ amixer -c 0 cget numid=138 # 'Mic Jack'
: values=off
$ evtest --query /dev/input/event8 EV_SW SW_HEADPHONE_INSERT ; echo $?
0 # 0 = not inserted
evtest on the jack input device recorded zero events across two full
unplug/replug cycles, and dmesg gained no audio-related lines. Plug type is never
determined:
HPH Type = 0
HPHL Impedance = 0
HPHR Impedance = 0
What is correctly configured
This is not a missing-DT-node problem. Everything expected is present:
/proc/device-tree/audio-codecisqcom,wcd9395-codec/qcom,wcd9390-codecwith
full MBHC configuration:qcom,mbhc-headphone-vthreshold-microvolt = 50000qcom,mbhc-headset-vthreshold-microvolt = 1700000qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 …>qcom,micbias1-microvolt…qcom,micbias4-microvolt= 1800000
snd_soc_wcd_mbhcis loaded and referenced bysnd_soc_wcd939xwcd939x_usbssis loaded and bound at i2c1-000e- Both WCD939x SoundWire devices bound cleanly, and the jack registered:
[12.943194] wcd939x_codec audio-codec: bound sdw:2:0:0217:010e:00:4 … [12.943206] wcd939x_codec audio-codec: bound sdw:3:0:0217:010e:00:3 … [12.977916] input: SM8650-APS2 Headset Jack as /devices/platform/sound/sound/card0/input8 - The jack input device declares the right capabilities
(/sys/class/input/event8/device/capabilities/sw = d4→
SW_HEADPHONE_INSERT | SW_MICROPHONE_INSERT | SW_LINEOUT_INSERT | SW_JACK_PHYSICAL_INSERT)
There are no MBHC-related errors in dmesg at all. The only codec warning is benign:
[7.169097] wcd939x_codec audio-codec: supply vdd-px not found, using dummy regulator
Leading hypothesis (unconfirmed)
qcom,hphl-jack-type-normally-closed and qcom,ground-jack-type-normally-closed are
absent from the audio-codec node. If this board wires its jack detect switches
normally-closed, their absence would cause the driver to interpret every mechanical
interrupt as a removal rather than an insertion — never advancing to electrical
detection, and matching the observed evidence exactly (mechanical IRQs counted,
Elect Insert permanently 0).
This is a hypothesis, not a confirmed diagnosis. Someone with the board schematic or
the vendor DT should confirm the jack detect polarity before patching.
Bug 2 — UCM2 JackControl names a control that does not exist
Location
/usr/share/alsa/ucm2/Qualcomm/sm8650/APS2/HiFi.conf, line 52:
SectionDevice."Headphones" {
...
Value {
PlaybackPriority 200
PlaybackPCM "hw:${CardId},0"
PlaybackMixer "default:${CardId}"
PlaybackMixerElem "HP"
JackControl "Headset Jack" # <-- no such kcontrol
JackHWMute "Speaker"
}
}
Evidence
The card exposes exactly three iface=CARD jack controls, and Headset Jack is not
among them:
$ amixer -c 0 controls | grep "iface=CARD"
numid=140,iface=CARD,name='DP0 Jack'
numid=139,iface=CARD,name='Headphone Jack'
numid=138,iface=CARD,name='Mic Jack'
Headset Jack is the name of the ASoC jack (hence the input device
SM8650-APS2 Headset Jack), but the kcontrols are named after the jack pins —
Headphone Jack and Mic Jack. JackControl requires a kcontrol name.
Every other Qualcomm UCM profile in the tree uses the correct name, including the
sibling profile for the same SoC and the one for the next SoC generation:
$ grep -rn "JackControl" /usr/share/alsa/ucm2/Qualcomm/ | grep -i "headphone\|headset"
.../sm8650/QRD/HiFi.conf:45: JackControl "Headphone Jack" # correct
.../sm8750/MTP/HiFi.conf:47: JackControl "Headphone Jack" # correct
.../sm8550/HDK/HiFi.conf:43: JackControl "Headphone Jack" # correct
.../sc8280xp/HiFi.conf:48: JackControl "Headphone Jack" # correct
.../x1e80100/HiFi.conf:52: JackControl "Headphone Jack" # correct
.../sm8650/APS2/HiFi.conf:52: JackControl "Headset Jack" # WRONG
Only sm8650/APS2 — the profile this board matches — is wrong.
Observed effect
The port's availability is never evaluated. It stays permanently unknown rather than
flipping between available and unavailable:
[Out] Headphones: Headphones playback (type: Headphones, priority: 200,
availability group: Headset, availability unknown)
Compare HDMI0, whose JackControl "DP0 Jack" resolves correctly and therefore
reports real state:
[Out] HDMI0: DisplayPort 0 playback (type: HDMI, priority: 200,
availability group: DP0, not available)
Verified by A/B test: replacing only this one line and restarting PipeWire changes the
port from availability group: Headset, availability unknown to plain
availability unknown, confirming the string is being looked up and silently failing.
Important scoping note: this bug does not hide the Headphones sink. The profile
and sink are present and fully usable either way — confirmed by testing the stock,
unpatched file. It only breaks availability tracking, which is one of the two reasons
auto-switching never happens. Fixing this line alone will not restore
auto-switching, because Bug 1 means the correctly-named control would read off
forever anyway. Both bugs need fixing.
Fix
--- a/ucm2/Qualcomm/sm8650/APS2/HiFi.conf
+++ b/ucm2/Qualcomm/sm8650/APS2/HiFi.conf
@@
- JackControl "Headset Jack"
+ JackControl "Headphone Jack"The same wrong string appears again, already commented out, at line 74 in the disabled
Headset capture section — worth correcting at the same time.
The rest of the profile is correct
The Headphones device section is otherwise complete and valid. All 17 mixer controls
referenced by its EnableSequence exist on this card (verified individually):
CLSH Switch, HPHL_RDAC Switch, HPHR_RDAC Switch, HPHL_COMP Switch,
HPHR_COMP Switch, HPHL Switch, HPHR Switch, RX HPH Mode, RX_HPH PWR Mode,
RX_MACRO RX0 MUX, RX_MACRO RX1 MUX, RX INT0_1 MIX1 INP0, RX INT1_1 MIX1 INP0,
RX INT0 DEM MUX, RX INT1 DEM MUX, RX_CODEC_DMA_RX_0 Audio Mixer MultiMedia1,
HP Volume. Selecting the profile runs the sequence correctly and produces working
stereo audio.
Proof the analog path is healthy
Selecting the Headphones profile on the stock, unmodified configuration causes
UCM to apply the EnableSequence and produces clean stereo audio in the headphones:
$ pactl set-card-profile alsa_card.platform-sound "HiFi (Headphones, Speaker)"
$ amixer -D hw:0 cget "name=HPHL Switch" # -> on
$ amixer -D hw:0 cget "name=HPHR Switch" # -> on
$ amixer -D hw:0 cget "name=CLSH Switch" # -> on
$ amixer -D hw:0 cget "name=RX HPH Mode" # -> 4 (CLS_H_LOHIFI)
$ paplay --device=alsa_output.platform-sound.HiFi__Headphones__sink tone.wav
Each channel was additionally verified in isolation, driving the codec directly:
$ speaker-test -D hw:0,0 -c 2 -t sine -f 440 -s 1 # left -> audible, left earcup
$ speaker-test -D hw:0,0 -c 2 -t sine -f 440 -s 2 # right -> audible, right earcup
Both channels work and are correctly panned. (Note for anyone reproducing:
speaker-test -c 2 -t sine alternates channels, so a listener can easily mistake it
for a single working channel. Use -s 1 / -s 2 to isolate.)
DAPM confirmed symmetric power-up during playback:
HPHL PGA: On in 1 out 1 - R12297(0x3009) mask 0x80
HPHR PGA: On in 1 out 1 - R12297(0x3009) mask 0x40
HPHL_RDAC: On HPHR_RDAC: On RDAC1: On RDAC2: On
IN1_HPHL: On IN2_HPHR: On CLS_H_PORT: On VDD_BUCK: On
No OCP or PDM watchdog interrupts fired during playback
(HPH_L OCP detect, HPH_R OCP detect, HPHL/HPHR PDM WD INT all 0).
So the codec, class-H amplifier, rx-macro routing, SBU mux and physical jack wiring are
all fine. Only detection is broken.
Additional issue — no capture devices at all
The same UCM profile has both input sections commented out, so the device exposes no
microphone whatsoever (wpctl status shows zero sources) despite pcm2c/pcm3c
existing and MultiMedia3/4 Capture being present in aplay -l:
SectionDevice."Headset"(headset mic,hw:0,2,ADC2) — commented outSectionDevice."Mic"(bottom mic,hw:0,3,SMIC8) — commented out
Probably worth its own issue.
Behaviour on a Steam session (tested)
All of the following was checked on a live gamescope-session-plus@steam session with
gamepadui running, confirming by ear that Steam's own UI navigation sounds followed the
output.
The workaround needs no Steam restart. Steam follows both:
- a plain default-sink change within one profile (
Headphones↔Speaker) — Steam UI
audio moved to the new output immediately; and - a full profile change (
HiFi (HDMI0, Speaker)→HiFi (Headphones, Speaker)),
which destroys and recreates the sink nodes. Steam UI audio still followed, and all
four PipeWire clients (Steam,Steam Voice Settings,gamescope,
Chromium input) stayed connected throughout.
What does break Steam: restarting PipeWire or WirePlumber. This is only relevant
to anyone testing a UCM change via ALSA_CONFIG_UCM2, not to the workaround above.
After systemctl --user restart pipewire wireplumber pipewire-pulse:
gamescopeandChromium inputdisappear from the PipeWire client list and do not
reconnect;Steamstays listed but produces no streams- Steam goes completely silent even though the sinks are healthy (verified working via
paplayat the same time) - Steam's output-device menu shows stale ghost entries — e.g. a
DisplayPort 0
device that no longer exists in the active profile, so three "Built-in Audio" entries
appear where there are only two sinks
Recovery requires restarting the session, which closes and reopens the Steam UI:
systemctl --user restart gamescope-session-plus@steam.serviceAfterwards all four clients reconnect with fresh PIDs and audio works normally. Worth
mentioning in any docs that tell users to restart PipeWire on this platform.
Practical stopgap: expose the switch as two non-Steam shortcuts
Because switching has to be done by hand every time, and gamepadui's output-device menu
is several levels deep in the Quick Access Menu, it is much more usable as two library
entries. This is what I ended up doing on the affected device, and it works well enough
to live with until the kernel fix lands.
~/.local/bin/armada-audio-switch:
#!/bin/bash
# Switch audio output between speakers and the 3.5mm jack.
# Needed because WCD939x MBHC electrical jack detection never fires on this board,
# so PipeWire never switches outputs by itself.
set -uo pipefail
CARD="alsa_card.platform-sound"
HP_SINK="alsa_output.platform-sound.HiFi__Headphones__sink"
SPK_SINK="alsa_output.platform-sound.HiFi__Speaker__sink"
HP_PROFILE="HiFi (Headphones, Speaker)"
note() {
printf '%s\n' "$1"
command -v notify-send >/dev/null 2>&1 && notify-send -t 2500 "Audio output" "$1" 2>/dev/null
return 0
}
die() { note "$1"; exit 1; }
active_profile() {
pactl list cards 2>/dev/null | awk '/Active Profile:/{sub(/^\tActive Profile: /,""); print; exit}'
}
have_sink() { pactl list sinks short 2>/dev/null | grep -qF "$1"; }
# set-default-sink only affects NEW streams, so move the live ones too
move_streams() {
local target="$1" id
for id in $(pactl list sink-inputs short 2>/dev/null | cut -f1); do
pactl move-sink-input "$id" "$target" 2>/dev/null || true
done
}
set_default() {
local sink="$1" id
pactl set-default-sink "$sink" 2>/dev/null || die "failed to set default sink"
id=$(pactl list sinks short 2>/dev/null | grep -F "$sink" | cut -f1 | head -1)
# wpctl (not pactl) persists the choice to ~/.local/state/wireplumber/default-nodes
[ -n "${id:-}" ] && wpctl set-default "$id" 2>/dev/null || true
pactl set-sink-mute "$sink" 0 2>/dev/null || true
move_streams "$sink"
}
case "${1:-}" in
headphones|hp|jack)
# Headphones conflicts with HDMI0, so it exists only in the Headphones profile
if [ "$(active_profile)" != "$HP_PROFILE" ]; then
pactl set-card-profile "$CARD" "$HP_PROFILE" || die "could not select $HP_PROFILE"
for _ in $(seq 10); do have_sink "$HP_SINK" && break; sleep 0.3; done
fi
have_sink "$HP_SINK" || die "Headphones sink did not appear"
set_default "$HP_SINK"; note "Headphones (3.5mm)" ;;
speakers|speaker|spk)
# Speaker is in every HiFi profile, so no profile change needed
have_sink "$SPK_SINK" || die "Speaker sink not found"
set_default "$SPK_SINK"; note "Built-in speakers" ;;
*) echo "usage: ${0##*/} headphones|speakers" >&2; exit 2 ;;
esacThen two one-line launchers, since a Steam shortcut needs its own target per entry:
# ~/.local/share/armada-audio/Headphones.sh
#!/bin/bash
exec "$HOME/.local/bin/armada-audio-switch" headphones# ~/.local/share/armada-audio/Speakers.sh
#!/bin/bash
exec "$HOME/.local/bin/armada-audio-switch" speakersAdd both via Desktop Mode → Steam → Add a Non-Steam Game, which is the supported
route. Two details caught me out doing it headlessly:
- Non-Steam shortcuts live in
~/.local/share/Steam/userdata/<steamID3>/config/shortcuts.vdf, which is binary
VDF (0x00nested map,0x01string,0x02little-endian int32,0x08
terminator; root is\x00shortcuts\x00, file ends\x08\x08). Non-Steam appids
followcrc32(Exe + AppName) | 0x80000000, read back as a signed int32. - Steam rewrites that file when it exits, so it must be edited with Steam stopped
(systemctl --user stop gamescope-session-plus@steam.service) or the edit is silently
discarded.
Two caveats on the result: the shortcut flashes as "Running" for a moment because the
script exits immediately, and a future Steam client change to the shortcuts format could
drop the entries. The underlying script is unaffected either way.
Notes for packaging the fix
These UCM files are not owned by any RPM (rpm -qf → "not owned by any package")
and alsa-ucm-conf is not installed, so they ship directly in the Armada image rather
than coming from Fedora. The UCM fix therefore belongs in the Armada repo (and ideally
upstream alsa-ucm-conf), not in a Fedora package.
Armada is Fedora bootc and / is a read-only composefs overlay:
composefs / overlay ro,relatime,lowerdir+=/run/ostree/.private/cfsroot-lower,…
/dev/sda14 /etc btrfs rw,…
so /usr/share/alsa/ucm2 cannot be edited in place on a deployed system. For local
testing, alsa-lib 1.2.16.1 honours ALSA_CONFIG_UCM2 (confirmed present in
libasound.so.2.0.0), so a patched tree in a writable location plus a systemd user
drop-in setting Environment="ALSA_CONFIG_UCM2=…" on pipewire.service,
wireplumber.service and pipewire-pulse.service works without touching /usr or
requiring bootc usr-overlay. That is only needed for testing the UCM change, though —
the user-facing workaround is just the pactl set-card-profile above.
Anyone testing that way should note the Steam caveat above: applying the drop-in means
restarting PipeWire, which silently kills Steam's audio until the gamescope session is
restarted. Restart the session as part of the test, or the UCM change will look broken
when it is not.
Steps to reproduce
plug in 3.5mm headphones
Expected behavior
plugging in headphones should swap to that output
Actual behavior
continued playing via speakers
Additional comments
No response
Confirmations
- I have read the project's README and documentation.
- I searched existing issues and confirm this is not a duplicate.
- I can reproduce this issue on the latest Armada release (or I noted the exact release above).
- I attached relevant logs, screenshots, or a minimal reproduction if applicable.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Projects
- StatusShow more project fieldsIn progress
Activity