Skip to content

Fix TC358743 HDMI capture colors and CSI-stall recovery on rev 1.3 - #2

Draft
DatanoiseTV wants to merge 2 commits into
feat/video-hid-webui-overhaulfrom
fix/tc358743-vyuy-chroma
Draft

Fix TC358743 HDMI capture colors and CSI-stall recovery on rev 1.3#2
DatanoiseTV wants to merge 2 commits into
feat/video-hid-webui-overhaulfrom
fix/tc358743-vyuy-chroma

Conversation

@DatanoiseTV

Copy link
Copy Markdown
Owner

Brings up TC358743 HDMI-to-CSI capture on rev 1.3 silicon (DCDZ-H2C module). Two independent defects, one commit each. Stacked on feat/video-hid-webui-overhaul.

1. YUV422 luma/chroma order (byte_swap_en)

The TC358743 lands its YUV422 stream luma-first ([Y,C,Y,C] in memory, confirmed via a raw framebuffer hex dump) while the P4 JPEG encoder consumes chroma-first. The bytes were interleave-swapped, giving 2-pixel vertical stripes and wrong colours on solid fills.

Fix: enable the CSI bridge's byte_swap_en, which swaps the two bytes of each 16-bit YUV422 element in the DMA write path. Free hardware de-interleave, no extra pass, no fps cost (28 fps sustained). Supersedes the disabled BitScrambler reorder path (measured ~28 MB/s, far too slow for 30 fps).

2. CSI-stall recovery without HDMI re-enumeration

On rev 1.3 the TC358743 keeps a locked HDMI input (TMDS+SYNC in SYS_STATUS) while the P4 MIPI CSI-2 bridge stalls independently (RX FIFO fills, no line packets, DMA completions stop). The old recovery path treated every frame timeout as HDMI loss and dropped HPD, forcing the attached PC to re-enumerate the display on each stall — a visible reconnect/mode-change storm on the host.

Recovery is now split by what actually failed:

  • capture_hw_csi_rekick() — non-destructive path for "TC locked, CSI stalled". Restarts esp_cam and re-issues the TC CSI-2 TX start without touching HPD/EDID/TMDS, so the source never re-enumerates. Throttled by a cooldown.
  • capture_hw_csi_full_reinit() — escalation for a wedged D-PHY. esp_cam stop/start does not reset the D-PHY receiver; only a full teardown/recreate of the esp_cam CSI controller + ISP processor does. Rebuilds the stack, then re-issues the TC CSI start, still without cycling HPD.

handle_csi_timeout() checks SYS_STATUS: while locked it re-kicks; after N consecutive failed re-kicks it escalates to the full D-PHY reinit; only a genuine loss of lock falls back to the HPD-cycling recover. The esp_cam create/destroy is refactored into shared s_csi_stack_create()/s_csi_stack_destroy() helpers. A framebuffer hex dump (raw CSI word + encoder input) is added behind CONFIG_P4KVM_TC358743_ADV_DEBUG for byte-order/stall diagnosis.

Testing

Verified on hardware (ESP32-P4 rev 1.3 + TC358743, PC HDMI source): correct colours, stable capture over 2+ minutes across host sleep/wake, 28 fps at 4.28 Mb/s over the live MJPEG stream. Full IDF v6.0 build passes.

Known residual

A faint +8px horizontal echo remains on high-contrast text (81/370 text rows; luma full-res, no shear, colours correct). Under investigation; not a regression from this change and does not block the colour/stability fixes.

On rev 1.3 silicon the TC358743 keeps a locked HDMI input (TMDS+SYNC in
SYS_STATUS) while the P4 MIPI CSI-2 bridge stalls independently: the RX
FIFO fills, no line packets arrive, and DMA completions stop. The old
recovery path treated every frame timeout as HDMI loss and dropped HPD,
which forced the attached PC to re-enumerate the display on each stall -
a visible reconnect/mode-change storm on the host.

Split recovery by what actually failed:

- capture_hw_csi_rekick(): non-destructive path for the "TC locked but
  CSI stalled" case. Stops esp_cam, re-applies the CSI bridge config,
  restarts, and re-issues the TC's CSI-2 TX start WITHOUT touching
  HPD/EDID/TMDS, so the source never re-enumerates.
- capture_hw_csi_full_reinit(): escalation for a wedged D-PHY. esp_cam
  stop/start does not reset the D-PHY receiver; only a full teardown and
  recreate of the esp_cam CSI controller + ISP processor does. Destroys
  and rebuilds the stack, then re-issues the TC CSI start, still without
  cycling HPD.

handle_csi_timeout() now checks SYS_STATUS: while the input is locked it
re-kicks (throttled by HDMI_RECOVER_CSI_REKICK_COOLDOWN_US), and after
CSI_REKICK_ATTEMPTS_BEFORE_REINIT consecutive failed re-kicks escalates
to the full D-PHY reinit. Only a genuine loss of lock falls back to the
HPD-cycling capture_hw_hdmi_recover().

The esp_cam creation/destruction is refactored into
s_csi_stack_create()/s_csi_stack_destroy() so both init and the D-PHY
reinit share one code path. A frame-buffer hex dump (raw CSI word and
encoder input) is added behind CONFIG_P4KVM_TC358743_ADV_DEBUG for
diagnosing byte-order and stall issues.
On rev 1.3 silicon the TC358743 lands its YUV422 stream luma-first
([Y,C,Y,C] in memory, confirmed via the raw framebuffer hex dump) while
the P4 JPEG encoder consumes chroma-first. Without a reorder the luma
and chroma bytes are interleave-swapped, producing 2-pixel vertical
stripes and wrong colours on solid fills.

Enable the CSI bridge's byte_swap_en, which swaps the two bytes of each
16-bit YUV422 element in the DMA write path - a free hardware de-
interleave, no extra pass and no measured fps cost (28 fps sustained).
This supersedes the disabled BitScrambler reorder path; update the
CAPTURE_NEEDS_REORDER comment in capture_priv.h to reflect that the
reorder is now done by the byte swap rather than being unnecessary.
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