Skip to content

drm_fb_helper: re-probe on late EDID, don't clamp to fallback fb size#2198

Open
b1nc0d3x wants to merge 1 commit into
freebsd:mainfrom
b1nc0d3x:submit/d2-drm_fb_helper
Open

drm_fb_helper: re-probe on late EDID, don't clamp to fallback fb size#2198
b1nc0d3x wants to merge 1 commit into
freebsd:mainfrom
b1nc0d3x:submit/d2-drm_fb_helper

Conversation

@b1nc0d3x
Copy link
Copy Markdown

Summary

When a DRM connector's EDID becomes available after the kernel's initial drm_fb_helper_hotplug_event() pass, the connector ends up permanently stuck on the safe fallback framebuffer (typically 1024x768) and never picks up the panel's preferred mode.

Real-hardware case that motivated the fix: RockPro64 USB-C DisplayPort via the Cadence MHDP DPTX driver. The cdn-dp framer runs a 19-stage bring-up sequence (PHY init, link training, DPCD, EDID readback over AUX) that completes well after drm_fb_helper has already settled on the fallback fb. The connector's get_modes() returns the panel-preferred 1920x1080 timing, but the fb_helper code path drops it on the floor.

Two distinct bugs in drm_fb_helper_hotplug_event() / drm_setup_crtcs():

  1. If bound < crtcs_bound on the first pass, set delayed_hotplug=true and return early. The intent is "wait for more connectors to bind before reprobing", but on the late-EDID path the reprobe never runs again — nothing in the upstream cdn-dp path fires a synthetic hotplug after the framer comes up. Result: the safe fallback is permanent.

  2. drm_setup_crtcs() passes fb->width / fb->height as max_width / max_height to drm_helper_probe_single_connector_modes(). When fb is still the 1024x768 safe fallback, this filters out every panel mode that would actually be picked (1920x1080, 2560x1440, etc.).

Fix:

  1. Drop the delayed_hotplug short-circuit. Drivers that genuinely want to defer can return early from their own .fb_probe path; drm_fb_helper itself should not refuse to reprobe.

  2. Read max_width / max_height from the connector's drm_device->mode_config caps (dev->mode_config.max_width / max_height) instead of the in-flight fb dimensions.

Other DRM2 paths (HDMI via dw-hdmi, eDP via panel-simple, etc.) probe synchronously and are unaffected — they had their EDID available before drm_fb_helper_hotplug_event() was first called.

Test plan

  • RockPro64 USB-C DP with a 1920x1080 panel (XYM W156F1 portable monitor): before patch, fb stays at 1024x768 forever even after cdn-dp logs EDID parsed: preferred 1920x1080 @ 60. After patch, fb resizes to 1920x1080 within the same hotplug callback that follows EDID readback.
  • RockPro64 HDMI with the same panel via DVI adapter: no regression (this path was already synchronous, so the change is a no-op for it).
  • Boot test on a generic amd64 desktop with i915 + DP-attached monitor: no regression (verified mode list unchanged via sysctl hw.dri.0).

Suggested reviewers

manu, hselasky, johalun, ray — DRM / arm64 maintainers per git log on sys/dev/drm2/. Not @-mentioned directly; happy to ping on request.

Notes

Companion to a series of patches landing the RockPro64 USB-C DisplayPort + audio path. This one is independent and useful for any DRM2 driver whose connector probes EDID asynchronously.

Author: Kyle Crenshaw <B1nc0d3x@gmail.com>

@b1nc0d3x b1nc0d3x requested a review from bsdimp as a code owner May 14, 2026 21:10
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 14, 2026

Thank you for taking the time to contribute to FreeBSD!

Some of files have special handling:

Important

@bsdimp wants to review changes to sys/dev/drm2

When a DRM connector's EDID becomes available *after* the kernel's
initial drm_fb_helper_hotplug_event() pass, the connector ends up
permanently stuck on the safe fallback framebuffer (typically
1024x768) and never picks up the panel's preferred mode.

Real-hardware case: RockPro64 USB-C DisplayPort via the Cadence MHDP
DPTX driver.  The cdn-dp framer runs a 19-stage bring-up sequence
(PHY init, link training, DPCD, EDID readback over AUX) that
completes well after drm_fb_helper has already settled on the
fallback fb.  The connector's get_modes() returns the panel-preferred
1920x1080 timing, but the fb_helper code path drops it on the floor.

Two distinct bugs in drm_fb_helper_hotplug_event() / drm_setup_crtcs():

1. If bound < crtcs_bound on the first pass, set delayed_hotplug=true
   and return early.  On the late-EDID path the reprobe never runs
   again -- nothing in the upstream cdn-dp path fires a synthetic
   hotplug after the framer comes up.  Result: the safe fallback is
   permanent.

2. drm_setup_crtcs() passes fb->width / fb->height as max_width /
   max_height to drm_helper_probe_single_connector_modes().  When fb
   is still the 1024x768 safe fallback, this filters out every panel
   mode that would actually be picked (1920x1080, 2560x1440, etc.).

Fix:

1. Drop the delayed_hotplug short-circuit.  Drivers that genuinely
   want to defer can return early from their own .fb_probe path;
   drm_fb_helper itself should not refuse to reprobe.

2. Read max_width / max_height from the connector's drm_device->
   mode_config caps (dev->mode_config.max_width / max_height)
   instead of the in-flight fb dimensions.

Other DRM2 paths (HDMI via dw-hdmi, eDP via panel-simple, etc.)
probe synchronously and are unaffected.

Signed-off-by: Kyle Crenshaw <B1nc0d3x@gmail.com>
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