Repository navigation
Surface 2 / Surface RT: WM8962 silent — the I2S and MCLK pins are never muxed (MUX UNCLAIMED) #141
Description
Follow-up to #140 and #108, from the Surface 2 (Tegra 4 / T114) side. Audio is silent there too, and I found something that I do not think has been raised in either thread: the I2S and MCLK pins are never muxed at all.
Kernel: linux-postmarketos-grate 7.0.1 (libre-tegra stable), Raspbian 12 userland, booted via UEFI + EFI stub.
The finding
tegra114-microsoft-surface-2-common.dtsi contains no audio pinmux entries whatsoever, and the pins confirm it at runtime:
# /sys/kernel/debug/pinctrl/70000868.pinmux/pinmux-pins
pin 2 (DAP2_FS PA2): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 3 (DAP2_SCLK PA3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 4 (DAP2_DIN PA4): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 5 (DAP2_DOUT PA5): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 180 (CLK1_OUT PW4): (MUX UNCLAIMED) (GPIO UNCLAIMED)
The card is on 70080400.i2s = tegra_i2s1, i.e. DAP2, and MCLK is pmc clk_out_1 = CLK1_OUT PW4 (extperiph1). Counting audio pin entries per board:
| board | audio pin entries |
|---|---|
tegra114-microsoft-surface-2-common.dtsi |
0 |
tegra30-microsoft-surface-rt.dts |
0 |
tegra114-dalmore.dts |
26 |
tegra114-asus-tf701t.dts |
17 |
So the SoC generates MCLK (pmc_clk_out_1 at 12.288 MHz, verified in clk_summary) and the I2S controller DMAs happily (hw_ptr advancing), but neither the clock nor the data can physically reach the codec. That is consistent with a codec whose registers all look perfect over I2C while nothing comes out, and with the headphone DC servo timing out, since the DC servo needs SYSCLK.
Adding the pins (values copied from dalmore) makes them claim correctly:
pin 2 (DAP2_FS PA2): 70000868.pinmux (GPIO UNCLAIMED) (HOG) function i2s1 group dap2_fs_pa2
pin 180 (CLK1_OUT PW4): 70000868.pinmux (GPIO UNCLAIMED) (HOG) function extperiph1 group clk1_out_pw4
Honesty first: this did NOT restore audio on my Surface 2. Still silent on speakers and headphones. So it is either not the only fault, or the pins were already correct in hardware and pinctrl simply was not describing them. But given #140 reports the same silence on Surface RT, and Surface RT's DTS has the same omission, it seemed worth putting in front of people who know the hardware.
Confirming @digetx's point in #140
both 5v and 1.8v regulators are defined as always-on in device-tree and driver doesn't care about actual voltages, hence the change shall have no practical effect
Confirmed experimentally. Surface 2's DTS points all eight wm8962 supplies at a stub_audio_reg placeholder (regulator-fixed, no voltage, no parent, with a // TODO check regulators comment). I repointed them at the real vdd-1v8 rail (tps65913_smps8) — no change, exactly as predicted, because that rail is already regulator-always-on.
I also tested the related theory that Linux switches off what UEFI enabled: rebuilt with regulator_ignore_unused, which does change behaviour (SYSEN1 stays enabled where it was previously disabled on every boot) — but audio remained silent.
Ruled out on Surface 2, so nobody repeats it
- MCLK chain verified live while streaming:
pll_a368.64 MHz →pll_a_out0/extern1/pmc_clk_out_112.288 MHz,i2s13.072 MHz - Codec registers correct:
R26=0x01f8(DACs + HP/SPK PGAs powered),R49=0x00c3(Class-D enabled),R5=0x0010(DAC not muted) - DAPM path complete on both outputs (
Int Spk: On in 2,Headphone Jack: On in 4);SPKOUTL PGAis a mux takingDACLdirectly, soR99=0is expected rather than a fault - Jack detection correct, volume keys work (both GPIO paths — they work precisely because they do not use the I2S pins)
- TPS65090 FET3 and FET7 enabled at runtime via i2c:
POWER_GOODnever asserts, so nothing is behind them - wm8962 GPIOs 2/3/5/6 driven to logic-output-high at runtime (
0x0041, perwm8962_gpio_direction_out): no effect, so nothing obvious gates an external amp - The codec's own beep generator, routed internally to the DACs with the whole chain powered, is also inaudible — which is what makes me think the remaining fault is analogue rather than anything in the digital/routing path
I deliberately did not touch palmas LDO4: it is vpp-fuse on the Tegra 4 reference design, and a mistake there is irreversible.
Question
Has anyone ever had wm8962 audio working on either Surface RT or Surface 2? #140 suggests not. If it has never worked on either, that reframes this as an unfinished port rather than a per-unit fault, and the pinmux omission above might be worth checking on Surface RT hardware by someone who has one.
Also happy to send patches for three unrelated Surface 2 device-tree fixes found along the way, all confirmed working on hardware, if they would be useful:
ti,palmas-override-powerholdon the palmas node — without it the machine halts but never powers down (GPIO7 POWERHOLD outranks theDEV_ONbit), requiring a 10-second hardware force-off- microSD slot:
sdmmc3enabled with its supplies, and its pins taken back fromuarta(upstream currently trades the SD slot for a serial console) ti,tps65090-chargersubnode — the driver was probing and failing with "no platform data available" (already present in 7.0.1; the fix applies to older DTBs)
Happy to test anything on Surface 2 hardware.
Activity
zefr0g commentedon Sep 4, 2026
Patches for the two confirmed fixes mentioned above, against libre-tegra
stable(7.0.1). Both tested on Surface 2 hardware. The third (audio pins/supplies) is described in the issue body — happy to send it too, but it does not fix audio, so it is descriptive-correctness only.1. Power-off
2. microSD slot
zefr0g commentedon Sep 4, 2026
Solved — it is a wm8962 codec-driver bug, not the device tree, not the pins, not the rails. Sound confirmed on Surface 2, and confirmed again after a clean boot with the patched kernel: no
DC servo timed outat all,SYSCLK_ENA/CP_ENAread 1 during playback, DC servo completes.What is wrong
wm8962_configure_bclk()(mainlinesound/soc/codecs/wm8962.c, unchanged) provisionally setsSYSCLK_ENAso that the read-onlyDSPCLK_DIVfield becomes valid, then clears it unconditionally whenever the bias level is belowSND_SOC_BIAS_ON:That bit is owned by the
SYSCLKDAPM supply widget — andwm8962_mic_detect()force-enables that pin. The Tegra machine driver callswm8962_mic_detect(), so on Surface RT / Surface 2 DAPM writesSYSCLK_ENA = 1once at card init and, because the widget never changes power state again, never writes it again. The first stream's transition toBIAS_PREPAREcallsconfigure_bclk(), which clears the bit behind DAPM's back. From then on every stream plays with SYSCLK off: DACs do not run,CP_ENArefuses to latch,hp_event()reportsDC servo timed out, and the codec is silent although every register DAPM believes in looks perfect.Only boards that call
wm8962_mic_detect()are affected — i.e. the Tegra machine driver — which is exactly why it is "both Surfaces, nobody else".How it was found
Diffed the driver's regmap cache (
/sys/kernel/debug/regmap/2-001a/registers) against raw I2C reads of the chip during playback:R8 = 0x09C7in both, i.e.SYSCLK_ENA = 0, whiledebugfs/asoc/.../dapm/SYSCLKsaysOn (forced) … R8 mask 0x20. Forcing bit 5 of R8 over I2C during a stream:CP_ENAlatches immediately, the DC servo completes in 56 ms, and there is sound — first time ever under Linux on this unit. So MCLK does reach the codec, the analogue supplies are fine, and DAP2/I2S1 is correct.Side note for anyone reading the earlier posts: the "registers look correct" checks were reading the cache, not the chip.
Fix
Full patch with commit message: https://gist.github.com/zefr0g/97ff52172502ccde6a23dfd6c71608fc (against libre-tegra
stable7.0.1; applies to mainline unchanged). I'll send it to alsa-devel as well. Surface RT owners from #140: this should fix you too — the Tegra machine driver is the same.Bonus: the Windows ACPI tables
The firmware's ACPI tables survive in memory under Linux (
efi: ACPI 2.0=0xfdf1c014, readable via/dev/mem). TheAUDIdevice confirms the DTS wiring (codec on I2C3/0x1a, hp-det PW2, IRQ PX3) and adds one output-only GPIO for the codec, PR6 / GPIO 142, that no DTS has; UEFI leaves it high and toggling it made no audible difference, but it may be an amp mute worth describing. No ACPI power resources are attached to the audio device, confirming the rails are always-on. Happy to share the decompiled tables.zefr0g commentedon Sep 4, 2026
Pull request with the codec fix: #142. The three Surface 2 device-tree fixes (power-off, microSD, audio pinmux/supplies) are on https://github.com/zefr0g/linux/tree/surface2-fixes rebased on libre-tegra
stable7.0.1, since this repo'smasterdoes not carry the Surface 2 DTS.wmjb commentedon Sep 5, 2026
surface 1 / 2 audio always worked fine from 5.17 up until 6.4 kernel. after 6.4 kernel wm8962 was given it's own code file and some incorrect assumptions at pmos were made about it regarding the new file, they were taken from our 3.4 android kernel, which also had the same incorrect assumptions regarding mic switch, but it didn't hang the codec leading to no sound on that kernel. a couple of points regarding both devices surface 1 and 2. there is no mic enable switch in the hardware, the mic are always physically routed to the sound soc. the regulators are hard wired, always on, there is no enabling or disabling them. the fix you have above is correct.. do not set bias on mic, this is legacy hack nonsense from nvidia dev boards, never should it be done in a production board, nvidia have some really bad practices in the early days, probably still do. if the codec is already powered it waits for MICBIAS to stabilise, which it never does and hangs there forever leaving the codec init incomplete. regarding the sd card, that's just left over from using the sdcard as a serial uart for the initial bringup we did of the kernel on this device, none of this was changed on this repo, because we don't use this repo or the pmos kernel to produce the kernels for the surface 1 / 2 at Open-Surface-RT
zefr0g commentedon Sep 8, 2026
Thanks for the reply.
should i post this patch to https://github.com/Open-Surface-RT/grate-linux ?
digetx commentedon Sep 9, 2026
Merged the PR. The grate-linux hasn't been updated in a while and the expectation is that upstream kernel should be used instead and grate-linux only contains WIP patches staged for upstreaming. The grate driver also was forked to https://codeberg.org/libre-tegra, I don't know about its status but it looks active and you may get in touch with people there.
digetx commentedon Sep 9, 2026
See now you already mentioned the libre-tegra. Any reason you haven't contributed fix there?
digetx commentedon Sep 9, 2026
Again, if the fix is relevant to upstream kernel, i.e. upstream kernel works on your surface2 and has same audio bug, please send fix to upstream.