Skip to content

fix(viewer): re-assert linuxfb display mode after HDMI hotplug#3075

Open
vpetersson wants to merge 2 commits into
masterfrom
fix/linuxfb-hdmi-hotplug-resolution
Open

fix(viewer): re-assert linuxfb display mode after HDMI hotplug#3075
vpetersson wants to merge 2 commits into
masterfrom
fix/linuxfb-hdmi-hotplug-resolution

Conversation

@vpetersson

Copy link
Copy Markdown
Contributor

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×768 is the kernel's drm_fb_helper hard-coded fallback mode — 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 the 1024×768 default. 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 went disconnected, but the CRTC/plane/fb held 1080p throughout).

Fix

A linuxfb-only watchdog in start_viewer.sh:

  • watches the HDMI connector for a disconnected → connected transition,
  • waits for EDID/DDC to settle (ANTHIAS_HOTPLUG_SETTLE_SECONDS, default 5),
  • 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,
  • 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. A QT_QPA_PLATFORM guard 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/fb0 or /dev/dri, and its /sys is read-only, so the mode re-assert is impossible there.)

Validation (real Pi 3 testbed)

  • eglfs (pi3-64): a real ~10 s HDMI unplug held 1920×1080 across the whole event (1660/1660 samples) → confirmed not the affected path.
  • linuxfb (pi3): confirmed no process holds /dev/dri/card0 (so drm_fb_helper solely owns /dev/fb0), then drove a disconnect → 1024×768 → reconnect cycle. The watchdog detected the reconnect, re-asserted 1920×1080, and restarted the viewer:
    [baseline] geometry=1920x1080
    TV off          -> status=disconnected
    racy fallback   -> geometry 1024x768 (virt stays 1920x1080)
    TV on           -> watchdog: "HDMI reconnect — re-asserted 1920x1080 ...; restarting viewer."
    [after]    geometry=1920x1080   viewer RESTARTED
    

Note: the 1024×768 latch was simulated with fbset — the testbed monitor presents EDID instantly and can't reproduce the real no-EDID race that the reporter's TV triggers. Detection (connector reconnect) and recovery (re-assert preferred mode) are identical regardless of how the mode got latched.

🤖 Generated with Claude Code

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>
@vpetersson vpetersson requested a review from a team as a code owner June 12, 2026 12:42
@vpetersson vpetersson requested a review from Copilot June 12, 2026 12:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@vpetersson vpetersson requested a review from Copilot June 12, 2026 13:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review any files in this pull request.

@sonarqubecloud

Copy link
Copy Markdown

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.

[BUG] TV resolution incorrect since update

2 participants