Skip to content

docs: capture sensor-side WDR via /mnt/mtd/Config/wdrmode.dat on Sofia#156

Merged
widgetii merged 1 commit intomasterfrom
docs/wdr-mode-capture
May 4, 2026
Merged

docs: capture sensor-side WDR via /mnt/mtd/Config/wdrmode.dat on Sofia#156
widgetii merged 1 commit intomasterfrom
docs/wdr-mode-capture

Conversation

@widgetii
Copy link
Copy Markdown
Member

@widgetii widgetii commented May 4, 2026

Documents the procedure for capturing sensor-side WDR mode init from a XiongMai Sofia build, after the multi-step investigation that turned up several false leads.

TL;DR of the new section

Sofia's runtime DVR-IP BroadTrends.AutoGain knob does not reconfigure the sensor — it lands in Public_LinearWDR_SwitchLibXmCap_System_switchWdrModeXmCap_IspVi_switchWdrMode which only reads the ISP attr (the misleading HI_MPI_ISP_SetWDRMode failed error string is a copy-paste relic from a refactor) and persists the new mode to /mnt/mtd/Config/wdrmode.dat via libdvr.so's SetWdrMode (a thin fopen + fwrite of a 4-byte LE int). The sensor-side mode dispatch happens at the next Sofia startup: Sofia reads wdrmode.dat and calls cmos_set_image_mode(mode) inside the per-sensor driver, which then runs the alternative init register table.

So the actual procedure is:

printf '\x02\x00\x00\x00' > /mnt/mtd/Config/wdrmode.dat ; sync   # mode 2 = line-WDR
killall Sofia ; sleep 1
WDR_TRACE=/utils/dumps/mode2.log /usr/bin/Sofia </dev/null \
    > /utils/dumps/mode2-stdout.log 2>&1 &                       # via bind-mount wrapper
sleep 30 ; killall ipctool-upx Sofia

Then verify the right mode fired by grep'ing Sofia's stdout for the per-mode banner (linear mode / 2to1 line WDR ... / LINE Init OK).

Worked example: IMX291 + CV300 + Sofia

metric mode 0 (linear) mode 2 (line-WDR)
trace size 20 KB 51 KB
total writes 70 140
Sofia banner linear mode 2to1 half frame WDR mode + 60fps LINE Init OK
segmenter phases init(106) init(106) + mode_switch_1(114)

WDR-only registers: 0x3007=0x00, 0x3009=0x02, 0x3018=0x6D, 0x3046=0xE1, 0x300A=0xF0, 0x3014=0x20, 0x3020/0x3021 — Sony's IMX29x DOL configuration block.

Tooling unchanged

trace_segment.py's existing find_mode_switches heuristic (added in #149, generalised in #152) catches Sofia's two-pass init as init + mode_switch_1 with no code changes — works because Sofia's cmos_set_image_mode per-mode init wraps each register table between a standby-assert/release pair on the family's stream-control register, which is exactly what the heuristic looks for.

trace_to_driver.py emits the WDR body as <sensor>_set_mode_1 next to <sensor>_linear_init, all gcc -Wall -Wextra clean.

Diagnostic added

The new section ends with a recipe for answering "does my sensor have WDR firmware in this Sofia build?":

$ strings /usr/bin/Sofia | grep -E '_init  |LINE Init OK' | sort -u
~~~~~~~~~~AR0237_init  JJ ~~~~~~~~~          ← linear-only
--IMX291 1080P 60fps LINE Init OK!           ← has WDR
--IMX290 1080P 30fps LINE Init OK!           ← has WDR
~~~~~~~~~~IMX323_init  gjj ~~~~~~~~~         ← linear-only

A sensor with only ~~~_init~~~ markers is linear-only on that build; wdrmode.dat writes still get persisted but produce no sensor-side effect.

Also generalises the Segmenter heuristic note

The existing paragraph said find_mode_switches watches for 0x100=0 → 0x100=1. That was true only for SmartSens; #152 made the function take whichever (reg, init_val, stream_val) tuple find_init_bounds matched on. The note now reads "the same stream-control register pair that the matched init_pattern used", with explicit examples for SmartSens / Sony IMX / SOI/JX.

Test plan

  • tools/test_pipeline.sh (CI smoke test) — passes
  • No tooling changes — purely docs

🤖 Generated with Claude Code

Documents what's actually needed to capture sensor-mode reconfiguration
on a XiongMai Sofia build, after we walked through the false leads:

* Sofia's runtime DVR-IP `BroadTrends.AutoGain` knob does NOT
  reconfigure the sensor. The path is `Public_LinearWDR_Switch` ->
  `LibXmCap_System_switchWdrMode` -> `XmCap_IspVi_switchWdrMode`,
  which calls `HI_MPI_ISP_GetPubAttr`, optionally does a VI
  unbind/rebind, and persists the new mode to
  `/mnt/mtd/Config/wdrmode.dat` via `libdvr.so`'s `SetWdrMode`
  (a thin `fopen + fwrite`). It does not call
  `HI_MPI_ISP_SetWDRMode` and does not invoke any sensor-driver
  code. Confirmed empirically on two boards: zero `0x100` (SmartSens)
  / `0x3000` (Sony) cycles after `AutoGain` toggle.

* The actual sensor-side mode dispatch happens at Sofia startup:
  Sofia reads wdrmode.dat (4-byte LE int) and calls
  `cmos_set_image_mode(mode)` inside the per-sensor driver. For
  Sony IMX29x the case-set is 0=linear, 2=line-WDR (DOL),
  3=half-frame WDR, 4=full-frame WDR.

* Procedure: write the desired mode to wdrmode.dat with `printf
  '\x02\x00\x00\x00' > ...`, kill Sofia, restart under the bind-mount
  trace wrapper. Sofia at startup picks up the new mode and the trace
  captures the alternative init register sequence.

* Worked example: Hi3516CV300 + IMX291 + Sofia. Mode 0 (linear)
  produced 70 writes; mode 2 (line-WDR) produced 140 writes with 17
  WDR-only register values (`0x3007=0x00`, `0x3009=0x02`,
  `0x3018=0x6D`, `0x3046=0xE1`, etc. - matching Sony's IMX29x DOL
  configuration). `trace_segment.py`'s existing `find_mode_switches`
  heuristic catches the two-pass init as `init` + `mode_switch_1`
  with no changes; `trace_to_driver.py` emits the WDR body as
  `<sensor>_set_mode_1`.

* Diagnostic: which sensors in your Sofia binary have WDR firmware
  vs being linear-only? Grep the binary for `_init  ` debug markers
  and `LINE Init OK` banners. A sensor with both has multi-mode
  drivers; one with only `_init` is linear-only and `wdrmode.dat`
  changes are no-ops at the sensor level (the file still gets
  persisted, but no sensor-driver code path responds).

Also generalises the existing "Segmenter heuristic" note from the
hardcoded SmartSens `0x100` pair to "the stream-control register pair
the matched `init_pattern` used", with explicit Sony IMX and SOI/JX
examples - reflects the actual code in `trace_segment.py` post-#152.

No tooling changes; CI `test-extraction-pipeline` passes unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@widgetii widgetii merged commit e1f92fe into master May 4, 2026
3 checks passed
@widgetii widgetii deleted the docs/wdr-mode-capture branch May 4, 2026 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant