Skip to content

Fix HDMI never locking: select the video input before loading the bitstream - #19

Open
ScreenSensitive wants to merge 1 commit into
Modos-Labs:mainfrom
ScreenSensitive:upstream/hdmi-input-order
Open

Fix HDMI never locking: select the video input before loading the bitstream#19
ScreenSensitive wants to merge 1 commit into
Modos-Labs:mainfrom
ScreenSensitive:upstream/hdmi-input-order

Conversation

@ScreenSensitive

Copy link
Copy Markdown

Problem

HDMI does not work. DisplayPort over USB-C is unaffected, and nothing in the log indicates a failure.

Cause

start_display_pipeline() calls restart_fpga() first and apply_input_selection() last. apply_input_selection() runs adv7611_early_init() / adv7611_init(), so the bitstream is loaded — and the gateware starts trying to lock — before the input is selected, and the decoder is then re-initialised underneath it, resetting its pixel clock and reasserting HPD_EN.

syslog shows the decoder initialising twice, the second time after FPGA up:

[0.234]  ADV7611 initialization done
[1.977]  ADV7611 initialization done      <- after "FPGA up"
[2.014]  Input status 01, measured 0 x 0, total 0 x 0

DisplayPort is unaffected because the PTN3460 isn't disturbed the same way, which is why this presents as an HDMI fault rather than an ordering problem.

Fix

Split the existing work so the frontend bring-up happens before restart_fpga(), leaving only the CSR_INPUT_CTRL write after it since that register needs the FPGA running. Both frontends stay powered on INPUT_SEL_AUTO and caster_input_request_auto() is still used, so hot-plug auto-switching is unchanged.

Also wait for an input to go live before loading the bitstream. Sampling immediately is not sufficient: 35 ms after adv7611_init() nothing reads as live even against a host that is already sending, and the decoder took ~1.1 s to report lock — so the wrong input gets committed and HDMI never comes up. The wait costs nothing when a source is present, since it exits as soon as it sees signal, and it also covers powering the board and host on together where the host takes far longer to start driving.

The reload path after video loss deliberately does not wait — video has just gone away, so there is nothing to wait for, and waiting there delays the no-signal state by the full timeout. It honours a minimum interval between reloads instead; without that a flapping input reloads the bitstream continuously and the panel visibly flashes.

Testing

13.3" 1600x1200 Paper Dev Kit, fpga-8bit-mono.bit, macOS host over HDMI.

  • Before: Input status 01, measured 0 x 0
  • After: Input status 3a [TMDS STABLE SUPPORTED LIVE], measured 1600 x 1200
  • Auto-switching between USB-C and HDMI verified, including hot-plug
  • Unplugging HDMI reloads in 156 ms; replugging recovers automatically

Narrowed by testing the pieces separately: powering down the unselected frontend and requesting TMDS explicitly also fix HDMI, but are unnecessary and would remove auto-switching, so neither is included.

Notes

  • Tested on one host and one panel, on the 1.0 gateware. This branches from main (ed94ef7f); it also rebases cleanly onto the 1.1 tag, which only touches log_input_status(). I have not tested against the gateware submodule bump in 1.1.
  • VIDEO_INPUT_WAIT_MS is chosen conservatively rather than derived; the measured requirement was ~1.1 s.
  • Please feel free to modify, rework or split this however suits the codebase — or take just the diagnosis and implement it differently. The polling wait in particular may be better done event-driven off HPD. No attachment to this exact shape.

HDMI never locks: the panel stays black while DisplayPort over USB-C works.

start_display_pipeline() calls restart_fpga() first and
apply_input_selection() last. apply_input_selection() runs
adv7611_early_init() and adv7611_init(), so the bitstream is loaded and the
gateware begins trying to lock before the input is selected, and the decoder
is then re-initialised underneath it -- resetting its pixel clock and
reasserting HPD. The decoder initialises twice, the second time after
"FPGA up", and the input then reports status 01 with measured 0 x 0.

DisplayPort is unaffected because the PTN3460 is not disturbed the same way,
which is why this appears as an HDMI fault rather than an ordering problem.

Split the existing work so the frontend bring-up happens before
restart_fpga(), leaving only the CSR_INPUT_CTRL write after it since that
register needs the FPGA running. Both frontends stay powered on
INPUT_SEL_AUTO and caster_input_request_auto() is still used, so hot-plug
auto-switching is unchanged.

Also wait for an input to go live before loading the bitstream. Sampling
immediately is not enough: 35 ms after adv7611_init() nothing reads as live
even against a host already sending, and the decoder took around 1.1s to
report lock, so the wrong input gets committed. The wait is generous because
it costs nothing when a source is present -- it exits as soon as it sees
signal -- and it also covers powering the board and host on together, where
the host can take far longer to start driving.

The reload path after video loss deliberately does NOT wait, since video has
just gone away and there is nothing to wait for; waiting there delayed the
no-signal state by the full timeout. It instead honours a minimum interval
between reloads, without which a flapping input reloads the bitstream
continuously and the panel visibly flashes.

Tested on a 13.3" 1600x1200 Paper Dev Kit with fpga-8bit-mono.bit against a
macOS host. Before: status 01, measured 0 x 0. After: status 3a
[TMDS STABLE SUPPORTED LIVE], measured 1600 x 1200. Auto-switching between
USB-C and HDMI verified including hot-plug; unplugging HDMI reloads in
156 ms and replugging recovers automatically.
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