cd /news/ai-tools/retroid-pocket-duo-lite-running-main… · home › topics › ai-tools › article
[ARTICLE · art-162571] src=forum.level1techs.com ↗ pub= topic=ai-tools verified=true sentiment=· neutral

Retroid Pocket Duo Lite running mainline Debian: gaps left, help needed

A community-maintained mainline Debian port for the Retroid Pocket Duo Lite is missing working microphone capture because upstream Linux never wired the VA macro's DMIC clock enable into the TX macro, according to a technical reply drafted with Anthropic's Claude and posted in the project's forum thread. The reply argues the fix is a device-tree change rather than a sound-card rewrite: add a VA macro node modeled on sm8250.dtsi's vamacro with qcom,dmic-sample-rate = <2400000>, add a va-dai-link using VA_CODEC_DMA_TX_0, and route "VA DMIC2" to "MIC BIAS1" instead of the TX DMIC2 path. The author notes the vendor bolero_dmic_clk_enable register tables at 0x3084/0x3088/0x308c/0x3090 with enable masks 1/2/4/8 match mainline's va_dmic_clk_enable() in lpass-va-macro.c, and that the SWR_DMICn_CTL register only selects a SoundWire mic clock.

read7 min views1 publishedNov 2, 2026

Hello Brotha! I dunno much about any of this, but, I can point Fable at it. So, I did. 10 mins of compute from Anthropics flag ship coming at ya. My morning on the internet is filled with neckbeard passive aggressive vitriol possibly rooted in some new AI inferiority complex. So, I don’t wanna be that guy. I hope this helps. “Reviewing a forum post about mainline Linux setup.

Reviewing a forum post about mainline Linux setup.

I’ll pull the repo and look at the actual device tree and audio config before answering, since the SM6125 audio/Venus issues are very configuration-specific.

Ran 21 commands

I cloned the repo and read docs/MICROPHONE.md, docs/SPEAKERS-NEXT.md, docs/HELP-WANTED.md and the gaming/Venus scripts, then checked them against the upstream drivers (lpass-tx-macro.c, lpass-va-macro.c, aw88166.c, venus pm_helpers.c/ hfi_venus.c, gcc-sm6125.c). There are a few things he’s missed, and one of them (the mic) looks like a real “obvious in hindsight” answer. Here’s a reply you can post more or less as-is:

Read through the repo — nice work, especially the measured docs. A few things that I think you’ve missed, in order of how confident I am.

Your own disassembly already contains the answer. The vendor bolero_dmic_clk_enable tables (0x3084/0x3088/0x308c/0x3090, enable masks 1/2/4/8) are the VA macro’s DMIC0..3_CTL registers plus the freq-change bits in VA_TOP_CSR_DMIC_CFG. Mainline has that exact sequence already: va_dmic_clk_enable() in sound/soc/codecs/lpass-va-macro.c writes the same registers with the same masks. On Bolero the MSM DMIC clock pads are generated by the VA macro, full stop; the vendor TX macro just calls across into it.

Upstream never wired that cross-call. In lpass-tx-macro.c, "TX DMIC0..7" are plain SND_SOC_DAPM_INPUT s — nothing runs when you capture through them. The SWR_DMICn_CTL register you fought with is only a clock select for SoundWire mics (CDC_TX_SWR_DMIC_CLK_SEL_MASK, bits 3:1), which is why bit 0 never latched: it isn’t an enable. So “TX DMIC2 → TX_CODEC_DMA_TX_3” can never produce a PDM clock on mainline. Not a bug you can patch around in TX.

Why your hand-poke of the VA registers didn’t work either: nothing has voted the VA macro’s core clock with the ADSP (that’s what the bolero_clk_rsc_request_clock layer you found does — it’s an AFE clock request, q6afecc in mainline). Without a bound VA macro driver, MMIO writes to the macro latch fine and nothing clocks. “Values stick, audio doesn’t appear” is exactly that.

The part I think you’ve got wrong: VA_CODEC_DMA_TX_0 is a legacy q6afe port, not an audioreach one.sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c lists VA_CODEC_DMA_TX_0 right next to the TX_CODEC_DMA_TX_3 you already use, and qrb5165-rb5.dts captures DMICs through it with plain q6afe/ q6asm — no SPF firmware. Since CDC-DMA ports already work on your ADSP (TX_3 does), VA_0 almost certainly does too; Android uses it for hotword.

So the fix is a DT change, not a sound-card rewrite:

Add a VA macro node modelled on sm8250.dtsi’s vamacro (qcom,sm8250-lpass-va-macro, clocks mclk/ macro/ dcodec from &q6afecc, #clock-cells, clock-output-names = "fsgen"). Take the real reg base and clock IDs from the va-macro node in your extracted Android DTB — you already have extract-android-dtb.sh.

qcom,dmic-sample-rate = <2400000> (the driver refuses to probe without it; 9.6 MHz / 4 matches the vendor’s 0x249f00). DMIC pinctrl can stay on your gpio127/128 pair.

Add a va-dai-link copied from RB5: cpu <&q6afedai VA_CODEC_DMA_TX_0>, platform <&q6routing>, codec <&vamacro 0>.

Routing: "VA DMIC2", "MIC BIAS1" (replacing the "TX DMIC2", "MIC BIAS1" line — same mux index, pair 1, just on the VA side). Then VA DMIC MUX0 = DMIC2 and VA_AIF1_CAP Mixer DEC0 instead of the TX controls.

Retroid’s Duo port doing it through VA wasn’t about audioreach; it’s that VA is the only macro on mainline that owns the DMIC clock.

Two states the vendor driver writes at runtime that live in the AW88166’s DSP RAM, not in registers:

Calibrated Re. The vendor driver loads the factory speaker-resistance calibration (persist partition, aw_cali-style file) into the DSP. Mainline only does it if you set the Calib ALSA control, and aw_dev_update_cali_re() silently ignores out-of-range values — so right now the smart-PA algorithm is running on whatever default is baked into dsp_cfg. A protection algorithm with a wrong Re will clamp output.

vmax. The vendor aw_monitor code raises the boost-voltage ceiling in DSP memory based on battery level. Mainline aw88166.c doesn’t touch vmax at all. If the ACF default is conservative and Android’s monitor table lifts it at full battery, you’d get exactly “identical registers, much quieter”.

A decisive cheap test before digging: push software gain to 2–4× (PipeWire allows >1.0, e.g. wpctl set-volume <id> 3.0). If it gets much louder (even if it clips), the amps had headroom and your problem is input level on the ADSP side. If it barely changes, the amp’s DSP is limiting, and Re/vmax is where to look. Then find the calibration value on the Android persist partition and feed it to Calib, and have parse-acf.py dump the monitor section for vmax.

The pa stop check fail:0x0330 is consistent with this family: 0x0330 is PLLS/CLKS still set, i.e. the amp is told to stop while the bit clock is still running. Ordering, cosmetic — your note is right.

“20 % vs 100 % makes no difference” can’t happen with software volume — that’s 14 dB. It means WirePlumber picked a hardware mixer element for this card and the writes are going nowhere. Side-step it:

monitor.alsa.rules = [
  { matches = [ { device.name = "~alsa_card.*" } ]
    actions = { update-props = { api.alsa.soft-mixer = true } } }
]

Slider works immediately, and Plasma’s “raise maximum volume” then gives you 150 % for free.

On the amixer crash: rc 134 is abort() from alsa-lib’s own assert in snd_ctl_elem_info() — the element id it was handed has neither a name nor a numid. That’s not the kernel’s ELEM_INFO being broken; it’s the element list containing a blank entry. Run amixer -c0 controls (that only uses ELEM_LIST) and look for an entry with an empty name or numid 0; that control is the culprit, probably from one of the machine-driver or topology patches.

“venus_gdsc off, zero users, clk_src never enabled” is what you’d read after a failed init — the driver powers everything back down on failure. It doesn’t tell you anything about the moment it failed. failed to reset venus core comes from hfi_venus.c after venus_boot_core() polled CTRL_STATUS and the firmware CPU never signalled init. Which means PAS auth (or the no-TZ load) had already returned OK, the GDSCs were on, and the clocks were enabled by core_power_v4(). The core just didn’t run. Two things to check, in order:

Firmware. On a production (fused) device the TZ only runs a venus image signed by the OEM’s chain, and the load address must be the one Android reserves. Use the device’s own venus.mbn from the firmware partition you already mount for the modem/ADSP, and make sure memory-region matches the Android DTB’s pil_video_mem. Confirm in dmesg which path ran ( core->use_tz) and that qcom_pas_auth_and_reset returned 0.

GCC clocks. SM6125 differs from SM6115 here: the video block’s bus clocks are in GCC, separate from the videocc you wrote. Upstream gcc-sm6125.c marks only gcc_video_ahb_clk and gcc_video_xo_clk CLK_IS_CRITICAL; gcc_video_axi0_clk (0x1701c), gcc_video_throttle_core_clk and gcc_qmip_video_vcodec_ahb_clk stay off unless something references them. A firmware CPU with no AXI path to DDR is precisely a boot_core timeout. Quick experiment: temporarily flag those three CLK_IS_CRITICAL in gcc-sm6125.c, or reference GCC_VIDEO_AXI0_CLK as the node’s bus clock the way bengal references GCC_VENUS_CTL_AXI_CLK. The vendor DTB’s qcom,vidc node clock-names list is the authority for which GCC clocks it expects.

Also sample clk_summary and the GDSC state during the probe (blacklist venus_core, modprobe it by hand with a loop reading debugfs in another shell), not after. And the apps_smmu SIDs you have (0x860/0x880) are bengal’s; take trinket’s from the vendor DTB — that won’t cause the boot timeout but it’s the next wall.

Hope that helps — the mic one in particular should be a weekend, not a rewrite.

Two notes for you, Mud Butt: I’m confident on the mic analysis (it’s straight from the upstream source and matches his own vendor disassembly) and on the PipeWire soft-mixer fix. The speaker Re/vmax theory and the Venus GCC-clock theory are well-grounded but unverified — I phrased them as tests to run rather than fixes, and you may want to keep that framing. He also mentions emailing Retroid; nothing above needs them.

Sources:

testyfishy/duolinux — docs/MICROPHONE.md, docs/SPEAKERS-NEXT.md, docs/HELP-WANTED.md, docs/STATE.md

lpass-va-macro.c / lpass-tx-macro.c

qrb5165-rb5.dts (VA Capture dai-link), sm8250.dtsi (vamacro node)

q6dsp-lpass-ports.c, aw88166.c

venus/pm_helpers.c, venus/hfi_venus.c, gcc-sm6125.c”

── more in #ai-tools 4 stories · sorted by recency
── more on @retroid pocket duo lite 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/retroid-pocket-duo-l…] indexed:0 read:7min 2026-11-02 · —