[BUG] sof-soundwire Jack event doesn't work properly
Describe the bug
On my machine 3.5mm does not detect properly (in evtest), while force set cs42l43 Jack Override make it work properly.
To Reproduce
- Plug a headphone or headset into the 3.5mm jack
- Run
sudo evtestand select the/dev/input/event16device (sof-soundwire Jack) - Observe the reported switch events
$ sudo evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
...
/dev/input/event16: sof-soundwire Jack
/dev/input/event17: sof-soundwire HDMI/DP,pcm=5
/dev/input/event18: sof-soundwire HDMI/DP,pcm=6
/dev/input/event19: sof-soundwire HDMI/DP,pcm=7
...
Select the device event number [0-19]: 16
Input driver version is 1.0.1
Input device ID: bus 0x0 vendor 0x0 product 0x0 version 0x0
Input device name: "sof-soundwire Jack"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 114 (KEY_VOLUMEDOWN)
Event code 115 (KEY_VOLUMEUP)
Event code 164 (KEY_PLAYPAUSE)
Event code 582 (KEY_VOICECOMMAND)
Event type 5 (EV_SW)
Event code 2 (SW_HEADPHONE_INSERT) state 0
Event code 4 (SW_MICROPHONE_INSERT) state 0
Event code 6 (SW_LINEOUT_INSERT) state 0
Event code 7 (SW_JACK_PHYSICAL_INSERT) state 0
Event code 8 (SW_VIDEOOUT_INSERT) state 0
Properties:
Testing ... (interrupt to exit)
Event: time 1762625239.970797, type 5 (EV_SW), code 6 (SW_LINEOUT_INSERT), value 1
Event: time 1762625239.970797, type 5 (EV_SW), code 7 (SW_JACK_PHYSICAL_INSERT), value 1
Event: time 1762625239.970797, -------------- SYN_REPORT ------------
SW_HEADPHONE_INSERT and SW_MICROPHONE_INSERT don't change when a headphone is plugged in (instead SW_LINEOUT_INSERT and SW_JACK_PHYSICAL_INSERT are being set to 1).
Reproduction Rate All the time
Expected behavior
At least SW_HEADPHONE_INSERT and SW_MICROPHONE_INSERT (if with mic) should be set while plug in/out
Impact 3.5mm jack malfunction
Environment
-
Branch name and commit hash of the 2 repositories: sof (firmware/topology) and linux (kernel driver).
- ArchLinux
- Kernel: 6.17.7-arch1-1
- SOF: 2025.05.1-1
-
Name of the topology file
- Topology: intel/sof-ipc4-tplg/sof-lnl-cs42l43-l0-4ch.tplg
-
Name of the platform(s) on which the bug is observed.
- Machine: Lenovo Yoga 9 2-in-1 14ILL10
- Platform: LNL Ultra 7 258V
- Codec: Cirrus Logic CS42L43 (SoundWire MIPI interface)
Screenshots or console output
Adding @charleskeepax @simontrimmer for codec.
This feels like it could be something to do with this headset.
- Do you have another headset you can try for comparison?
- And what is the make/model of this headset?
This feels like it could be something to do with this headset.
- Do you have another headset you can try for comparison?
- And what is the make/model of this headset?
@charleskeepax I ve tested with some device that working in windows, but work weird in linux
- 3.5mm headset -> work
- 3.5mm headset (cable removable), cable only (same cable as 1) -> not work
- 3.5mm male to 3.5mm female without conneted any in female -> not work
- 3.5mm male to 3.5mm female with headset (same cable as 3, headset as 1) -> work
- 3.5mm male to 3.5mm male without conneted device -> not work
- 3.5mm male to 3.5mm male (same cable as 5) with my external powered spaeker -> not work
seams it trying to detect headset/devices impedance, but if connected device have large impedance it wont be recognize as a headphone
At least it should be a fallback if pluged in device impedance are high enough, it will become a headphone or CTIA
And lastly if using 3 ring 3.5mm spliter to split microphone and headphone
- without any device connnected to -> not work
- only connect headphone -> not work
- only connect microphone -> work
headset :kz saga KZ ZVX Pro TRN EMX
cable: lindy 3.5mm no brand 3.5mm
external powered speaker: GigaWorks T40 Series II
seams it trying to detect headset/devices impedance, but if connected device have large impedance it wont be recognize as a headphone
That is basically expected behaviour, the only real way to determine the difference between a line load and a headphone is the impedance which is typically much lower for a headphone.
From your first set of test cases: 1,4 - These are connecting a headset and it works, so super. 2,3,5 - These are just connecting an open-circuit cable, extension cables are tricky as its not super clear what the "correct" action is. 6 - This is connecting a line load and reports as line so this is also working at the kernel level, I suspect the problem here is that the current UCM doesn't hook up any routing for a lineout.
- For cases 2,3,5 what do you see reported? In your initial report you said both LINEOUT and PHYSICAL, which makes sense for case 6, however in cases 2,3,5 I would have expected only PHYSICAL to be reported?
- As for your splitter case, could you clarify what is reported in each case here as well?
@charleskeepax
2,3,5 and 6 case report the same in evtest, they are both report LINEOUT and PHYSICAL, what you said only report PHYSICAL is happened when inserting spliter with only headphone connected.
Indeed, in ucm there is no conf handle so-called LINEOUT, but I don't figireout how to write a line out ucm either.
$ amixer -c 0 controls | grep -i 'CARD'
numid=92,iface=CARD,name='HDMI/DP,pcm=5 Jack'
numid=98,iface=CARD,name='HDMI/DP,pcm=6 Jack'
numid=104,iface=CARD,name='HDMI/DP,pcm=7 Jack'
numid=89,iface=CARD,name='Headphone Jack'
numid=90,iface=CARD,name='Headset Mic Jack'
in ucm conf it handle profile enable by
JackControl "Headphone Jack" and JackControl "Headset Mic Jack" in Value section, and in alsa it seems no card named Line Out Jack ? (there is no corresponding cset and volume control like cs42l43 Headphone L Input 1, cs42l43 Headphone Digital Volume)
(https://github.com/alsa-project/alsa-ucm-conf/blob/master/ucm2/sof-soundwire/cs42l43.conf)
if ignore JackControl and make a conf, the same EnableSequence cset won't work for line-out (case6)
Ah yes that is correct we need to add a LINEOUT jack control into the kernel as well to enable the UCM.
Weird that 2,3,5 show as lineout + physical. Could you (hopefully your kernel has CONFIG_DYNAMIC_DEBUG) enable debug for cs42l43-jack.c:
echo "file sound/soc/codecs/cs42l43-jack.c +p" > /sys/kernel/debug/dynamic_debug/control
And then send though a log of plugging in the extension cable. If you also had a multimeter to measure the impedance between poles 3,4 on the extension cable that would be awesome.
I will endeavor to find some time to retest extension cables here, and hopefully some to add the lineout control, but please bear with me a little we are unfortunately very busy at this end right now.
Hmm.. ok so had a little poke on this mine does report only physical for an extension cable not sure why yours is reporting both that and line. I would assume it was external circuity in your system but then it should apply for your splitter jack as well.
Looking through things in a little more detail I am not sure that we would really do anything different based on a headphone or a line at present in the UCM so kinda tempted that we could just fix this by adding lineout into the mask for headphones for now. We can always loop around and do more if additional requirements pop up.
Not sure if you are comfortable building kernels but if you are this is the small change I was trying out:
diff --git a/sound/soc/sdw_utils/soc_sdw_cs42l43.c b/sound/soc/sdw_utils/soc_sdw_cs42l43.c
index b415d45d520d0..3e8e2e3bdf7c5 100644
--- a/sound/soc/sdw_utils/soc_sdw_cs42l43.c
+++ b/sound/soc/sdw_utils/soc_sdw_cs42l43.c
@@ -44,7 +44,7 @@ static const struct snd_soc_dapm_route cs42l43_dmic_map[] = {
static struct snd_soc_jack_pin soc_jack_pins[] = {
{
.pin = "Headphone",
- .mask = SND_JACK_HEADPHONE,
+ .mask = SND_JACK_HEADPHONE | SND_JACK_LINEOUT,
},
{
.pin = "Headset Mic",
@charleskeepax log is here new_log.txt
Hmm.. ok so had a little poke on this mine does report only physical for an extension cable not sure why yours is reporting both that and line.
Is your extension cable trs or trrs?
On my device
- trrs extension with open end -> only
SW_JACK_PHYSICAL_INSERT- More detail: as long as Sleeve and R2 are open, you will get this result
- trs extension with open end ->
SW_JACK_PHYSICAL_INSERT+SW_LINEOUT_INSERT- trs shortcut Sleeve and R2, thus only have 3 pin
Connect this two different cable to speaker will have different results (in the beginning test 6 I used a trs male to male to connect the external speaker, if trrs used it should be SW_JACK_PHYSICAL_INSERT only because trrs Sleeve will always an open end)
that is (what i tested and observed)
- Sleeve and R2 are open (or impedance large enough), then no matter what condition other pins ->
SW_JACK_PHYSICAL_INSERTonly - Sleeve and R2 have impedence, then no matter what condition other pins ->
SW_JACK_PHYSICAL_INSERT+SW_MICROPHONE_INSERT+SW_HEADPHONE_INSERT - under Sleeve and R2 are shortcut (this equivalent to insert a male trs):
- Tip and R1 are open (or impedance large enough) ->
SW_JACK_PHYSICAL_INSERT+SW_LINEOUT_INSERT - Tip and R1 have impedence ->
SW_JACK_PHYSICAL_INSERT+SW_HEADPHONE_INSERT
- Tip and R1 are open (or impedance large enough) ->
as for impedance
- most haedphone I used < 50 Ω.
- I have device that can add haedphone up to ~ 600 Ω and i confirm it can be detect as haedphone.
- The external powered spaeker I measured it up to about 100K Ω, and it detected as
SW_LINEOUT_INSERT - the impedance of mic + splitter(without headphone) is ~1.5K Ω (which means mic is ~1.5K Ω)
~~for kernel i will tested, when i have free time~~, but this will remain issue if using trrs male to male to connect external speaker which only have SW_JACK_PHYSICAL_INSERT (that might equivalent to a headphone with broken mic or a speaker with trrs cable and leaving a mic hole for user)
Update: I've been built with your patch and it work in LINEOUT case (but using trrs cable issue remain), furthermore I tested
{
.pin = "Headphone",
.mask = SND_JACK_MECHANICAL,
},
it also work and trrs issue solved (exactly same behavior in Win11, i think it's ultimate solution, but dont know if it have any side effect)
trrs extension with open end -> only SW_JACK_PHYSICAL_INSERT More detail: as long as Sleeve and R2 are open, you will get this result trs extension with open end -> SW_JACK_PHYSICAL_INSERT + SW_LINEOUT_INSERT trs shortcut Sleeve and R2, thus only have 3 pin
Ah yes that would explain it, a 3 pole extension cable would short pole 3,4 so that would indeed return PHYSICAL + LINEOUT. My extension cable was a 4 pole.
Update: I've been built with your patch and it work in LINEOUT case (but using trrs cable issue remain), furthermore I tested it also work and trrs issue solved (exactly same behavior in Win11, i think it's ultimate solution, but dont know if it have any side effect)
Excellent, glad that lineout change works. I think we can upstream that bit fairly soon, see if there are any comments. Will need to have a little more of a think on the extension cable front, historically the ASoC maintainer hasn't been super keen on just reporting headphones for things that are clearly not headphones. But I can certainly see the argument that it does probably make for the best user experience that way, since we can't really do any further detection once the extension cable is connected.
@charleskeepax
Thank you, I think the issue have been correctly aware and had a possible/viable solution except for reporting way (need descuess with upper maintainer). This issue sould be closed?
Personally I would keep this issue open for now until we have at least some of the fix upstreamed.