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

> Source: <https://forum.level1techs.com/t/retroid-pocket-duo-lite-running-mainline-debian-gaps-left-help-needed/259882#post_2>
> Published: 2026-11-02 16:00:21+00:00

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:

```
# /etc/wireplumber/wireplumber.conf.d/50-duo-softmixer.conf
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](https://github.com/testyfishy/duolinux) — `docs/MICROPHONE.md`, `docs/SPEAKERS-NEXT.md`, `docs/HELP-WANTED.md`, `docs/STATE.md`

[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)

[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)

[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)

[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)”
