fix(viewer): re-assert linuxfb display mode after HDMI hotplug#3075
Conversation
On the 32-bit Pi 1-3 (linuxfb/Qt5) viewer, a TV on a power schedule that switches itself off and on can leave the display stuck at 1024x768 instead of its native resolution (issue #3052). Root cause is kernel-side, not anything Anthias writes: under dtoverlay=vc4-kms-v3d the linuxfb boards never take DRM master, so the kernel's drm_fb_helper owns the display mode. When the HDMI sink wakes, the connector re-probe can win the race against the sink's EDID/DDC coming back; the connector momentarily reports no valid modes and drm_fb_helper latches its hard-coded 1024x768 default. Qt's linuxfb plugin reads the framebuffer geometry once at startup and can't follow the change, so the picture stays stuck until the Pi is power-cycled. eglfs boards (pi4 / pi5 / pi3-64 / arm64) are immune: Qt holds DRM master and keeps its own modeset committed across the hotplug. Verified on a Pi 3-64 testbed that a real ~10 s HDMI unplug never left 1920x1080. Fix: a linuxfb-only watchdog in start_viewer.sh watches the HDMI connector for a disconnect->reconnect and, once EDID is readable again, re-asserts the connector's *preferred* mode (read live from the connector, never hard-coded, so any panel resolution is honoured) onto the framebuffer via the fbdev sysfs `mode` attribute, then restarts the viewer so Qt re-initialises against the restored mode. All access is under /sys in the already-privileged viewer container; no DRM master is taken, so it never conflicts with Qt's fbdev use. The QT_QPA_PLATFORM guard makes it a no-op on eglfs/wayland boards. Validated on a real Pi 3: forcing the connector through a disconnect -> 1024x768 -> reconnect cycle, the watchdog re-asserted 1920x1080 and restarted the viewer. (The 1024x768 latch was simulated with fbset because the testbed monitor presents EDID instantly and can't reproduce the real no-EDID race; detection and recovery are identical regardless of how the mode was latched.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot wasn't able to review any files in this pull request.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- exit wait_for_framebuffer when the host has fb0 but the container's stale /dev doesn't, so `restart: always` re-snapshots /dev - keep waiting quietly when genuinely headless (no sysfs fb0) to avoid the #2959 crash-loop - fixes the "self-heals on hotplug" case that a running container's devtmpfs snapshot silently broke Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Added commit daa7f8d (folded from #3134): |
- preserve interlaced scan type instead of forcing a progressive mode string (interlaced-native sinks were never matched) - log rejected /sys .../fb0/mode writes instead of returning silently, so a screen stuck at 1024x768 is diagnosable - watch every HDMI connector, seeded from current status, instead of binding one at startup (second micro-HDMI port / late connect) - normalize `pidof python` to a single PID so a multi-PID result can't disable the watchdog (also fixes the pre-existing kill -0 loop) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Ran a high-effort multi-agent review + on-device validation on the Pi 2 (
Note on the review's two top "CONFIRMED" findings (fallback mode string One design limitation left as-is (flagging, not fixing without a call): the 3s connector-status poll can miss a fast disconnect→reconnect, and an AVR/HDMI-switch that pins HPD |
- wait_for_framebuffer: sleep+re-check before the stale-devtmpfs exit so a /dev/fb0 node that lags its sysfs entry on a fresh start can't cause restart churn - monitor: default an unseeded connector to 'connected' so an unreadable-status seed race can't look like a reconnect edge and spuriously restart a display that never dropped - PID: select the oldest pidof result (the viewer, launched before any gst_fbdev_player.py helper) instead of the newest Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Second-pass high-effort review + end-to-end test on the Pi 2. Commit e8142db addresses the three (PLAUSIBLE) follow-up findings:
End-to-end validated on the real integrated stack (Pi 2,
→ viewer killed → container restarted → fb back at 1920×1080. The watchdog subshell + 3s poll were confirmed live, and the reassert write-to- |
|



Problem
Fixes #3052. On a 32-bit Pi 1-3 (linuxfb / Qt5) viewer, a TV on a power schedule (switches itself off and on) frequently comes back at 1024×768 instead of its native resolution. The Pi stays on the whole time; only a manual reboot restores the right resolution.
Root cause
The
1024×768is the kernel'sdrm_fb_helperhard-coded fallback mode — not anything Anthias writes. Underdtoverlay=vc4-kms-v3d, the linuxfb boards never take DRM master, so the kernel'sdrm_fb_helperowns the display mode. When the HDMI sink wakes, the connector re-probe can win the race against the sink's EDID/DDC coming back; the connector momentarily reports no valid modes anddrm_fb_helperlatches the1024×768default. Qt's linuxfb plugin reads the framebuffer geometry once at startup and can't follow a later mode change, so the picture stays stuck.eglfs boards (
pi4/pi5/pi3-64/arm64) are immune — Qt holds DRM master and keeps its own modeset committed across the hotplug. Verified on a Pi 3-64 testbed: a real ~10 s HDMI cable unplug never left 1920×1080 (connector wentdisconnected, but the CRTC/plane/fb held 1080p throughout).Fix
A linuxfb-only watchdog in
start_viewer.sh:disconnected → connectedtransition,ANTHIAS_HOTPLUG_SETTLE_SECONDS, default 5),modeattribute,All access is under
/sysin the already-privileged viewer container; no DRM master is taken, so it never conflicts with Qt's fbdev use. AQT_QPA_PLATFORMguard makes it a complete no-op on eglfs/wayland boards. (Celery was considered but is the wrong home — that container isn't privileged, has no/dev/fb0or/dev/dri, and its/sysis read-only, so the mode re-assert is impossible there.)Validation (real Pi 3 testbed)
pi3-64): a real ~10 s HDMI unplug held 1920×1080 across the whole event (1660/1660 samples) → confirmed not the affected path.pi3): confirmed no process holds/dev/dri/card0(sodrm_fb_helpersolely owns/dev/fb0), then drove adisconnect → 1024×768 → reconnectcycle. The watchdog detected the reconnect, re-asserted 1920×1080, and restarted the viewer:🤖 Generated with Claude Code