{"slug": "retroid-pocket-duo-lite-running-mainline-debian-gaps-left-help-needed", "title": "Retroid Pocket Duo Lite running mainline Debian: gaps left, help needed", "summary": "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.", "body_md": "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.\n\nReviewing a forum post about mainline Linux setup.\n\nI’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.\n\nRan 21 commands\n\nI 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:\n\nRead 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.\n\nYour 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.\n\nUpstream 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.\n\nWhy 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.\n\nThe 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.\n\nSo the fix is a DT change, not a sound-card rewrite:\n\nAdd 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`.\n\n`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.\n\nAdd a `va-dai-link` copied from RB5: cpu `<&q6afedai VA_CODEC_DMA_TX_0>`, platform `<&q6routing>`, codec `<&vamacro 0>`.\n\nRouting: `\"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.\n\nRetroid’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.\n\nTwo states the vendor driver writes at runtime that live in the AW88166’s DSP RAM, not in registers:\n\n**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.\n\n**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”.\n\nA 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.\n\nThe `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.\n\n“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:\n\n```\n# /etc/wireplumber/wireplumber.conf.d/50-duo-softmixer.conf\nmonitor.alsa.rules = [\n  { matches = [ { device.name = \"~alsa_card.*\" } ]\n    actions = { update-props = { api.alsa.soft-mixer = true } } }\n]\n```\n\nSlider works immediately, and Plasma’s “raise maximum volume” then gives you 150 % for free.\n\nOn 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.\n\n“`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:\n\n**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.\n\n**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.\n\nAlso 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.\n\nHope that helps — the mic one in particular should be a weekend, not a rewrite.\n\nTwo 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.\n\nSources:\n\n[testyfishy/duolinux](https://github.com/testyfishy/duolinux) — `docs/MICROPHONE.md`, `docs/SPEAKERS-NEXT.md`, `docs/HELP-WANTED.md`, `docs/STATE.md`\n\n[lpass-va-macro.c](https://github.com/torvalds/linux/blob/master/sound/soc/codecs/lpass-va-macro.c) / [lpass-tx-macro.c](https://github.com/torvalds/linux/blob/master/sound/soc/codecs/lpass-tx-macro.c)\n\n[qrb5165-rb5.dts](https://github.com/torvalds/linux/blob/master/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts) (VA Capture dai-link), [sm8250.dtsi](https://github.com/torvalds/linux/blob/master/arch/arm64/boot/dts/qcom/sm8250.dtsi) (`vamacro` node)\n\n[q6dsp-lpass-ports.c](https://github.com/torvalds/linux/blob/master/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c), [aw88166.c](https://github.com/torvalds/linux/blob/master/sound/soc/codecs/aw88166.c)\n\n[venus/pm_helpers.c](https://github.com/torvalds/linux/blob/master/drivers/media/platform/qcom/venus/pm_helpers.c), [venus/hfi_venus.c](https://github.com/torvalds/linux/blob/master/drivers/media/platform/qcom/venus/hfi_venus.c), [gcc-sm6125.c](https://github.com/torvalds/linux/blob/master/drivers/clk/qcom/gcc-sm6125.c)”", "url": "https://wpnews.pro/news/retroid-pocket-duo-lite-running-mainline-debian-gaps-left-help-needed", "canonical_source": "https://forum.level1techs.com/t/retroid-pocket-duo-lite-running-mainline-debian-gaps-left-help-needed/259882#post_2", "published_at": "2026-11-02 16:00:21+00:00", "updated_at": "2026-11-02 16:25:43.515579+00:00", "lang": "en", "topics": ["ai-tools", "artificial-intelligence"], "entities": ["Retroid Pocket Duo Lite", "Anthropic", "Claude", "Debian", "Linux", "Qualcomm SM6125"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/retroid-pocket-duo-lite-running-mainline-debian-gaps-left-help-needed", "markdown": "https://wpnews.pro/news/retroid-pocket-duo-lite-running-mainline-debian-gaps-left-help-needed.md", "text": "https://wpnews.pro/news/retroid-pocket-duo-lite-running-mainline-debian-gaps-left-help-needed.txt", "jsonld": "https://wpnews.pro/news/retroid-pocket-duo-lite-running-mainline-debian-gaps-left-help-needed.jsonld"}}