* [PATCH v4 0/3] sysfb: Fix display output on Lenovo D330 (and others)
@ 2026-09-04 9:06 Thomas Zimmermann
2026-09-04 9:07 ` [PATCH v4 1/3] firmware/sysfb: Remove rotation quirk for Lenovo D330 Thomas Zimmermann
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Thomas Zimmermann @ 2026-09-04 9:06 UTC (permalink / raw)
To: javierm, ardb, ilias.apalodimas, jani.nikula, maarten.lankhorst,
mripard, simona, airlied
Cc: dri-devel, linux-efi, sashiko-reviews, Thomas Zimmermann
The kernel mis-interprets the display geometry given by the Lenovo
D330 as incorrect. The values are correct, but the display output is
rotated by 90°. With the kernel's firmware quirk applied, the output
is garbled.
Remove the firmware quirk for the Lenovo D330 and let DRM's sysfb
drivers set the correct panel orientation instead. To make this work
for any display mode, use the panel size for looking up the correct
orientation.
Tested on a Lenovo D330-10IGM IdeaPad.
v4:
- fix test for EDID PTD (Jani)
v3:
- rename EDID helper to drm_edid_detect_panel_size()
- clean up EDID code (Jani)
- mention possible dependency on device firmware version
v2:
- reorder patches to have the immediate fix first
- detect and handle broken EDID better (Sashiko)
- fix width/height pointer check (Sashiko)
Thomas Zimmermann (3):
firmware/sysfb: Remove rotation quirk for Lenovo D330
drm/edid: Add drm_edid_detect_panel_size()
drm/sysfb: Use preferred panel size for panel orientation quirks
drivers/firmware/efi/sysfb_efi.c | 9 ------
drivers/gpu/drm/drm_edid.c | 47 ++++++++++++++++++++++++++++++++
drivers/gpu/drm/sysfb/efidrm.c | 17 +++++++++++-
drivers/gpu/drm/sysfb/ofdrm.c | 18 ++++++++++--
drivers/gpu/drm/sysfb/vesadrm.c | 17 +++++++++++-
include/drm/drm_edid.h | 2 ++
6 files changed, 97 insertions(+), 13 deletions(-)
base-commit: aa389a514292b196ae89c6515568b3329abeec63
--
2.55.0
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v4 1/3] firmware/sysfb: Remove rotation quirk for Lenovo D330 2026-09-04 9:06 [PATCH v4 0/3] sysfb: Fix display output on Lenovo D330 (and others) Thomas Zimmermann @ 2026-09-04 9:07 ` Thomas Zimmermann 2026-09-10 7:23 ` Javier Martinez Canillas 2026-09-04 9:07 ` [PATCH v4 2/3] drm/edid: Add drm_edid_detect_panel_size() Thomas Zimmermann 2026-09-04 9:07 ` [PATCH v4 3/3] drm/sysfb: Use preferred panel size for panel orientation quirks Thomas Zimmermann 2 siblings, 1 reply; 11+ messages in thread From: Thomas Zimmermann @ 2026-09-04 9:07 UTC (permalink / raw) To: javierm, ardb, ilias.apalodimas, jani.nikula, maarten.lankhorst, mripard, simona, airlied Cc: dri-devel, linux-efi, sashiko-reviews, Thomas Zimmermann The Lenovo D330 is a notebook with detachable display. The display is installed in landscape orientation, but the display mode is in portrait orientation. By default, the display output is rotated to the left by 90°. The sysfb quirk breaks the display by swapping display width and height; and thus mixing up the display geometry. Fix this by keeping the display as-is. The sysfb DRM drivers, usually efidrm, will pick the correct panel orientation for the display. The exact behavior might depend on the version of the BIOS release, but the exact version numbers of broken and good releases are unknown. Users are advised to update to the latest firmware. Tested on a Lenovo D330-10IGM IdeaPad with firmware 8NCN43WW. v3: - mention possible dependency on BIOS release in commit description Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Ard Biesheuvel <ardb@kernel.org> --- drivers/firmware/efi/sysfb_efi.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/firmware/efi/sysfb_efi.c b/drivers/firmware/efi/sysfb_efi.c index 685283bb7327..2338de73c62c 100644 --- a/drivers/firmware/efi/sysfb_efi.c +++ b/drivers/firmware/efi/sysfb_efi.c @@ -301,15 +301,6 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = { }, .callback = efifb_swap_width_height, }, - { - /* Lenovo D330 with 800x1280 or 1200x1920 portrait screen */ - .matches = { - DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, - "Lenovo ideapad D330-10IGM"), - }, - .callback = efifb_swap_width_height, - }, { /* * Lenovo IdeaPad Duet 3 10IGL5 and 10IGL5-LTE with -- 2.55.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v4 1/3] firmware/sysfb: Remove rotation quirk for Lenovo D330 2026-09-04 9:07 ` [PATCH v4 1/3] firmware/sysfb: Remove rotation quirk for Lenovo D330 Thomas Zimmermann @ 2026-09-10 7:23 ` Javier Martinez Canillas 2026-09-10 7:46 ` Thomas Zimmermann 0 siblings, 1 reply; 11+ messages in thread From: Javier Martinez Canillas @ 2026-09-10 7:23 UTC (permalink / raw) To: Thomas Zimmermann, ardb, ilias.apalodimas, jani.nikula, maarten.lankhorst, mripard, simona, airlied Cc: dri-devel, linux-efi, sashiko-reviews, Thomas Zimmermann Thomas Zimmermann <tzimmermann@suse.de> writes: Hello Thomas, > The Lenovo D330 is a notebook with detachable display. The display > is installed in landscape orientation, but the display mode is in > portrait orientation. By default, the display output is rotated to > the left by 90°. > > The sysfb quirk breaks the display by swapping display width and > height; and thus mixing up the display geometry. Fix this by keeping > the display as-is. The sysfb DRM drivers, usually efidrm, will pick > the correct panel orientation for the display. > > The exact behavior might depend on the version of the BIOS release, > but the exact version numbers of broken and good releases are unknown. > Users are advised to update to the latest firmware. > > Tested on a Lenovo D330-10IGM IdeaPad with firmware 8NCN43WW. > > v3: > - mention possible dependency on BIOS release in commit description > > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > Acked-by: Ard Biesheuvel <ardb@kernel.org> > --- > drivers/firmware/efi/sysfb_efi.c | 9 --------- > 1 file changed, 9 deletions(-) > > diff --git a/drivers/firmware/efi/sysfb_efi.c b/drivers/firmware/efi/sysfb_efi.c > index 685283bb7327..2338de73c62c 100644 > --- a/drivers/firmware/efi/sysfb_efi.c > +++ b/drivers/firmware/efi/sysfb_efi.c > @@ -301,15 +301,6 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = { > }, > .callback = efifb_swap_width_height, > }, > - { > - /* Lenovo D330 with 800x1280 or 1200x1920 portrait screen */ > - .matches = { > - DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), > - DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, > - "Lenovo ideapad D330-10IGM"), > - }, > - .callback = efifb_swap_width_height, > - }, Agreed that is better to rely on the information provided by the firmware, instead of having this quirk. Specially given that it breaks when the firmware provides the correct display geometry. Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> -- Best regards, Javier Martinez Canillas Core Platforms Red Hat ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 1/3] firmware/sysfb: Remove rotation quirk for Lenovo D330 2026-09-10 7:23 ` Javier Martinez Canillas @ 2026-09-10 7:46 ` Thomas Zimmermann 0 siblings, 0 replies; 11+ messages in thread From: Thomas Zimmermann @ 2026-09-10 7:46 UTC (permalink / raw) To: Javier Martinez Canillas, ardb, ilias.apalodimas, jani.nikula, maarten.lankhorst, mripard, simona, airlied Cc: dri-devel, linux-efi, sashiko-reviews Hi Am 10.09.26 um 09:23 schrieb Javier Martinez Canillas: > Thomas Zimmermann <tzimmermann@suse.de> writes: > > Hello Thomas, > >> The Lenovo D330 is a notebook with detachable display. The display >> is installed in landscape orientation, but the display mode is in >> portrait orientation. By default, the display output is rotated to >> the left by 90°. >> >> The sysfb quirk breaks the display by swapping display width and >> height; and thus mixing up the display geometry. Fix this by keeping >> the display as-is. The sysfb DRM drivers, usually efidrm, will pick >> the correct panel orientation for the display. >> >> The exact behavior might depend on the version of the BIOS release, >> but the exact version numbers of broken and good releases are unknown. >> Users are advised to update to the latest firmware. >> >> Tested on a Lenovo D330-10IGM IdeaPad with firmware 8NCN43WW. >> >> v3: >> - mention possible dependency on BIOS release in commit description >> >> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> >> Acked-by: Ard Biesheuvel <ardb@kernel.org> >> --- >> drivers/firmware/efi/sysfb_efi.c | 9 --------- >> 1 file changed, 9 deletions(-) >> >> diff --git a/drivers/firmware/efi/sysfb_efi.c b/drivers/firmware/efi/sysfb_efi.c >> index 685283bb7327..2338de73c62c 100644 >> --- a/drivers/firmware/efi/sysfb_efi.c >> +++ b/drivers/firmware/efi/sysfb_efi.c >> @@ -301,15 +301,6 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = { >> }, >> .callback = efifb_swap_width_height, >> }, >> - { >> - /* Lenovo D330 with 800x1280 or 1200x1920 portrait screen */ >> - .matches = { >> - DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> - DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, >> - "Lenovo ideapad D330-10IGM"), >> - }, >> - .callback = efifb_swap_width_height, >> - }, > Agreed that is better to rely on the information provided by the > firmware, instead of having this quirk. Specially given that it > breaks when the firmware provides the correct display geometry. The plan is to tell users to upgrade to the latest firmware if we hear about regressions. The update is available on Lenovo's homepage. If an update really isn't possible for a user, we should at least know which firmware revision is broken. Then we can add back the quirk only for that specific release. Best regards Thomas > > Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> > -- -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com GF: Jochen Jaser, Andrew McDonald, (HRB 36809, AG Nürnberg) ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 2/3] drm/edid: Add drm_edid_detect_panel_size() 2026-09-04 9:06 [PATCH v4 0/3] sysfb: Fix display output on Lenovo D330 (and others) Thomas Zimmermann 2026-09-04 9:07 ` [PATCH v4 1/3] firmware/sysfb: Remove rotation quirk for Lenovo D330 Thomas Zimmermann @ 2026-09-04 9:07 ` Thomas Zimmermann 2026-09-04 9:28 ` Jani Nikula 2026-09-10 8:10 ` Javier Martinez Canillas 2026-09-04 9:07 ` [PATCH v4 3/3] drm/sysfb: Use preferred panel size for panel orientation quirks Thomas Zimmermann 2 siblings, 2 replies; 11+ messages in thread From: Thomas Zimmermann @ 2026-09-04 9:07 UTC (permalink / raw) To: javierm, ardb, ilias.apalodimas, jani.nikula, maarten.lankhorst, mripard, simona, airlied Cc: dri-devel, linux-efi, sashiko-reviews, Thomas Zimmermann Add drm_edid_detect_panel_size() to extract the panel's preferred display resolution from a given EDID. Required for setting up DRM's panel orientation quirks in sysfb drivers. v4: - fix test for EDID PTD (Jani) v3: - mention use case in documentation (Jani) - use is_detailed_timing_descriptor() (Jani) - rename helper to drm_edid_detect_panel_size() v2: - handle EDID without pixel timing descriptor (Sashiko) - fix checks for width and height pointers Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Ard Biesheuvel <ardb@kernel.org> --- drivers/gpu/drm/drm_edid.c | 47 ++++++++++++++++++++++++++++++++++++++ include/drm/drm_edid.h | 2 ++ 2 files changed, 49 insertions(+) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 9990a836d0b6..1331efb4876c 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -7852,3 +7852,50 @@ bool drm_edid_is_digital(const struct drm_edid *drm_edid) drm_edid->edid->input & DRM_EDID_INPUT_DIGITAL; } EXPORT_SYMBOL(drm_edid_is_digital); + +/** + * drm_edid_detect_panel_size - Get a panel's size from EDID + * @drm_edid: EDID of the panel. + * @width: Returns the panel's width in pixels per scanline, if given + * @height: Returns the panel's height in scanlines, if given + * + * This function detects the preferred size of a panel from the given + * EDID. There is no such information stored in the EDID block directly, + * but the preferred mode often corresponds to the panel's native geometry. + * + * This helper should only be used during initialization before the + * connector is available. For regular use, retrieve the available display + * modes with the connector functions. + * + * Return: Zero on success, or a negative errno code otherwise. + */ +int drm_edid_detect_panel_size(const struct drm_edid *drm_edid, + unsigned int *width, unsigned int *height) +{ + const struct edid *edid = drm_edid->edid; + const struct detailed_timing *dt; + const struct detailed_pixel_timing *pt; + + /* + * Use display mode from the Preferred Timing Descriptor. For old + * and obscure displays, we might need better heuristics. + */ + + if (edid->revision < 4 || !(edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING)) + return -EINVAL; /* no Preferred Timing Descriptor */ + + dt = &edid->detailed_timings[0]; + + if (!is_detailed_timing_descriptor(dt)) + return -EINVAL; + + pt = &dt->data.pixel_data; + + if (width) + *width = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo; + if (height) + *height = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo; + + return 0; +} +EXPORT_SYMBOL(drm_edid_detect_panel_size); diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 04f7a7f1f108..a2617aa34edf 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -490,5 +490,7 @@ u32 drm_edid_get_panel_id(const struct drm_edid *drm_edid); bool drm_edid_match(const struct drm_edid *drm_edid, const struct drm_edid_ident *ident); bool drm_edid_has_quirk(struct drm_connector *connector, enum drm_edid_quirk quirk); +int drm_edid_detect_panel_size(const struct drm_edid *drm_edid, + unsigned int *width, unsigned int *height); #endif /* __DRM_EDID_H__ */ -- 2.55.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v4 2/3] drm/edid: Add drm_edid_detect_panel_size() 2026-09-04 9:07 ` [PATCH v4 2/3] drm/edid: Add drm_edid_detect_panel_size() Thomas Zimmermann @ 2026-09-04 9:28 ` Jani Nikula 2026-09-10 8:10 ` Javier Martinez Canillas 1 sibling, 0 replies; 11+ messages in thread From: Jani Nikula @ 2026-09-04 9:28 UTC (permalink / raw) To: Thomas Zimmermann, javierm, ardb, ilias.apalodimas, maarten.lankhorst, mripard, simona, airlied Cc: dri-devel, linux-efi, sashiko-reviews, Thomas Zimmermann On Fri, 04 Sep 2026, Thomas Zimmermann <tzimmermann@suse.de> wrote: > Add drm_edid_detect_panel_size() to extract the panel's preferred > display resolution from a given EDID. Required for setting up DRM's > panel orientation quirks in sysfb drivers. > > v4: > - fix test for EDID PTD (Jani) > v3: > - mention use case in documentation (Jani) > - use is_detailed_timing_descriptor() (Jani) > - rename helper to drm_edid_detect_panel_size() > v2: > - handle EDID without pixel timing descriptor (Sashiko) > - fix checks for width and height pointers > > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > Acked-by: Ard Biesheuvel <ardb@kernel.org> Given my shoddy comments before, not sure what it's worth, but, Reviewed-by: Jani Nikula <jani.nikula@intel.com> > --- > drivers/gpu/drm/drm_edid.c | 47 ++++++++++++++++++++++++++++++++++++++ > include/drm/drm_edid.h | 2 ++ > 2 files changed, 49 insertions(+) > > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c > index 9990a836d0b6..1331efb4876c 100644 > --- a/drivers/gpu/drm/drm_edid.c > +++ b/drivers/gpu/drm/drm_edid.c > @@ -7852,3 +7852,50 @@ bool drm_edid_is_digital(const struct drm_edid *drm_edid) > drm_edid->edid->input & DRM_EDID_INPUT_DIGITAL; > } > EXPORT_SYMBOL(drm_edid_is_digital); > + > +/** > + * drm_edid_detect_panel_size - Get a panel's size from EDID > + * @drm_edid: EDID of the panel. > + * @width: Returns the panel's width in pixels per scanline, if given > + * @height: Returns the panel's height in scanlines, if given > + * > + * This function detects the preferred size of a panel from the given > + * EDID. There is no such information stored in the EDID block directly, > + * but the preferred mode often corresponds to the panel's native geometry. > + * > + * This helper should only be used during initialization before the > + * connector is available. For regular use, retrieve the available display > + * modes with the connector functions. > + * > + * Return: Zero on success, or a negative errno code otherwise. > + */ > +int drm_edid_detect_panel_size(const struct drm_edid *drm_edid, > + unsigned int *width, unsigned int *height) > +{ > + const struct edid *edid = drm_edid->edid; > + const struct detailed_timing *dt; > + const struct detailed_pixel_timing *pt; > + > + /* > + * Use display mode from the Preferred Timing Descriptor. For old > + * and obscure displays, we might need better heuristics. > + */ > + > + if (edid->revision < 4 || !(edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING)) > + return -EINVAL; /* no Preferred Timing Descriptor */ > + > + dt = &edid->detailed_timings[0]; > + > + if (!is_detailed_timing_descriptor(dt)) > + return -EINVAL; > + > + pt = &dt->data.pixel_data; > + > + if (width) > + *width = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo; > + if (height) > + *height = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo; > + > + return 0; > +} > +EXPORT_SYMBOL(drm_edid_detect_panel_size); > diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h > index 04f7a7f1f108..a2617aa34edf 100644 > --- a/include/drm/drm_edid.h > +++ b/include/drm/drm_edid.h > @@ -490,5 +490,7 @@ u32 drm_edid_get_panel_id(const struct drm_edid *drm_edid); > bool drm_edid_match(const struct drm_edid *drm_edid, > const struct drm_edid_ident *ident); > bool drm_edid_has_quirk(struct drm_connector *connector, enum drm_edid_quirk quirk); > +int drm_edid_detect_panel_size(const struct drm_edid *drm_edid, > + unsigned int *width, unsigned int *height); > > #endif /* __DRM_EDID_H__ */ -- Jani Nikula, Intel ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 2/3] drm/edid: Add drm_edid_detect_panel_size() 2026-09-04 9:07 ` [PATCH v4 2/3] drm/edid: Add drm_edid_detect_panel_size() Thomas Zimmermann 2026-09-04 9:28 ` Jani Nikula @ 2026-09-10 8:10 ` Javier Martinez Canillas 2026-09-11 7:35 ` Jani Nikula 1 sibling, 1 reply; 11+ messages in thread From: Javier Martinez Canillas @ 2026-09-10 8:10 UTC (permalink / raw) To: Thomas Zimmermann, ardb, ilias.apalodimas, jani.nikula, maarten.lankhorst, mripard, simona, airlied Cc: dri-devel, linux-efi, sashiko-reviews, Thomas Zimmermann Thomas Zimmermann <tzimmermann@suse.de> writes: > Add drm_edid_detect_panel_size() to extract the panel's preferred > display resolution from a given EDID. Required for setting up DRM's > panel orientation quirks in sysfb drivers. > > v4: > - fix test for EDID PTD (Jani) > v3: > - mention use case in documentation (Jani) > - use is_detailed_timing_descriptor() (Jani) > - rename helper to drm_edid_detect_panel_size() > v2: > - handle EDID without pixel timing descriptor (Sashiko) > - fix checks for width and height pointers > > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > Acked-by: Ard Biesheuvel <ardb@kernel.org> > --- > drivers/gpu/drm/drm_edid.c | 47 ++++++++++++++++++++++++++++++++++++++ > include/drm/drm_edid.h | 2 ++ > 2 files changed, 49 insertions(+) > > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c > index 9990a836d0b6..1331efb4876c 100644 > --- a/drivers/gpu/drm/drm_edid.c > +++ b/drivers/gpu/drm/drm_edid.c > @@ -7852,3 +7852,50 @@ bool drm_edid_is_digital(const struct drm_edid *drm_edid) > drm_edid->edid->input & DRM_EDID_INPUT_DIGITAL; > } > EXPORT_SYMBOL(drm_edid_is_digital); > + > +/** > + * drm_edid_detect_panel_size - Get a panel's size from EDID > + * @drm_edid: EDID of the panel. > + * @width: Returns the panel's width in pixels per scanline, if given > + * @height: Returns the panel's height in scanlines, if given > + * > + * This function detects the preferred size of a panel from the given > + * EDID. There is no such information stored in the EDID block directly, > + * but the preferred mode often corresponds to the panel's native geometry. > + * > + * This helper should only be used during initialization before the > + * connector is available. For regular use, retrieve the available display > + * modes with the connector functions. > + * > + * Return: Zero on success, or a negative errno code otherwise. > + */ > +int drm_edid_detect_panel_size(const struct drm_edid *drm_edid, > + unsigned int *width, unsigned int *height) > +{ > + const struct edid *edid = drm_edid->edid; > + const struct detailed_timing *dt; > + const struct detailed_pixel_timing *pt; > + > + /* > + * Use display mode from the Preferred Timing Descriptor. For old > + * and obscure displays, we might need better heuristics. > + */ > + > + if (edid->revision < 4 || !(edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING)) > + return -EINVAL; /* no Preferred Timing Descriptor */ > + I saw that Jani and you discussed this logic in v3. I originally thought that your v3 was correct and this one was wrong, but I noticed now that this flag changed its semantic between 1.3 and 1.4. So I think that this latest version is correct indeed, 1.3 didn't include the native pixel format and 1.4 does not either if DRM_EDID_FEATURE_PREFERRED_TIMING flag is not set. Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> -- Best regards, Javier Martinez Canillas Core Platforms Red Hat ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 2/3] drm/edid: Add drm_edid_detect_panel_size() 2026-09-10 8:10 ` Javier Martinez Canillas @ 2026-09-11 7:35 ` Jani Nikula 0 siblings, 0 replies; 11+ messages in thread From: Jani Nikula @ 2026-09-11 7:35 UTC (permalink / raw) To: Javier Martinez Canillas, Thomas Zimmermann, ardb, ilias.apalodimas, maarten.lankhorst, mripard, simona, airlied Cc: dri-devel, linux-efi, sashiko-reviews, Thomas Zimmermann On Thu, 10 Sep 2026, Javier Martinez Canillas <javierm@redhat.com> wrote: > Thomas Zimmermann <tzimmermann@suse.de> writes: > >> Add drm_edid_detect_panel_size() to extract the panel's preferred >> display resolution from a given EDID. Required for setting up DRM's >> panel orientation quirks in sysfb drivers. >> >> v4: >> - fix test for EDID PTD (Jani) >> v3: >> - mention use case in documentation (Jani) >> - use is_detailed_timing_descriptor() (Jani) >> - rename helper to drm_edid_detect_panel_size() >> v2: >> - handle EDID without pixel timing descriptor (Sashiko) >> - fix checks for width and height pointers >> >> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> >> Acked-by: Ard Biesheuvel <ardb@kernel.org> >> --- >> drivers/gpu/drm/drm_edid.c | 47 ++++++++++++++++++++++++++++++++++++++ >> include/drm/drm_edid.h | 2 ++ >> 2 files changed, 49 insertions(+) >> >> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c >> index 9990a836d0b6..1331efb4876c 100644 >> --- a/drivers/gpu/drm/drm_edid.c >> +++ b/drivers/gpu/drm/drm_edid.c >> @@ -7852,3 +7852,50 @@ bool drm_edid_is_digital(const struct drm_edid *drm_edid) >> drm_edid->edid->input & DRM_EDID_INPUT_DIGITAL; >> } >> EXPORT_SYMBOL(drm_edid_is_digital); >> + >> +/** >> + * drm_edid_detect_panel_size - Get a panel's size from EDID >> + * @drm_edid: EDID of the panel. >> + * @width: Returns the panel's width in pixels per scanline, if given >> + * @height: Returns the panel's height in scanlines, if given >> + * >> + * This function detects the preferred size of a panel from the given >> + * EDID. There is no such information stored in the EDID block directly, >> + * but the preferred mode often corresponds to the panel's native geometry. >> + * >> + * This helper should only be used during initialization before the >> + * connector is available. For regular use, retrieve the available display >> + * modes with the connector functions. >> + * >> + * Return: Zero on success, or a negative errno code otherwise. >> + */ >> +int drm_edid_detect_panel_size(const struct drm_edid *drm_edid, >> + unsigned int *width, unsigned int *height) >> +{ >> + const struct edid *edid = drm_edid->edid; >> + const struct detailed_timing *dt; >> + const struct detailed_pixel_timing *pt; >> + >> + /* >> + * Use display mode from the Preferred Timing Descriptor. For old >> + * and obscure displays, we might need better heuristics. >> + */ >> + >> + if (edid->revision < 4 || !(edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING)) >> + return -EINVAL; /* no Preferred Timing Descriptor */ >> + > > I saw that Jani and you discussed this logic in v3. I originally thought that > your v3 was correct and this one was wrong, but I noticed now that this flag > changed its semantic between 1.3 and 1.4. > > So I think that this latest version is correct indeed, 1.3 didn't include the > native pixel format and 1.4 does not either if DRM_EDID_FEATURE_PREFERRED_TIMING > flag is not set. Yeah, and "pixel format" makes me think RGB, YCbCr, 4:4:4, 4:2:2, etc, *not* the resolution! Had to separately find the section that says pixel format means resolution here. BR, Jani. > > Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> -- Jani Nikula, Intel ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 3/3] drm/sysfb: Use preferred panel size for panel orientation quirks 2026-09-04 9:06 [PATCH v4 0/3] sysfb: Fix display output on Lenovo D330 (and others) Thomas Zimmermann 2026-09-04 9:07 ` [PATCH v4 1/3] firmware/sysfb: Remove rotation quirk for Lenovo D330 Thomas Zimmermann 2026-09-04 9:07 ` [PATCH v4 2/3] drm/edid: Add drm_edid_detect_panel_size() Thomas Zimmermann @ 2026-09-04 9:07 ` Thomas Zimmermann 2026-09-04 9:41 ` Jani Nikula 2026-09-10 8:11 ` Javier Martinez Canillas 2 siblings, 2 replies; 11+ messages in thread From: Thomas Zimmermann @ 2026-09-04 9:07 UTC (permalink / raw) To: javierm, ardb, ilias.apalodimas, jani.nikula, maarten.lankhorst, mripard, simona, airlied Cc: dri-devel, linux-efi, sashiko-reviews, Thomas Zimmermann Sysfb drivers currently use the given display mode for looking up the panel orientation. But the look-up table stores the native geometry of the panels, so the lookup fails if the current mode sizes differs. Get the panel's native geometry with drm_edid_detect_panel_size() from the EDID and use it for looking up the panel orientation. v2: - ofdrm: validate EDID header before using it (Sashiko) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Ard Biesheuvel <ardb@kernel.org> --- drivers/gpu/drm/sysfb/efidrm.c | 17 ++++++++++++++++- drivers/gpu/drm/sysfb/ofdrm.c | 18 ++++++++++++++++-- drivers/gpu/drm/sysfb/vesadrm.c | 17 ++++++++++++++++- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/sysfb/efidrm.c b/drivers/gpu/drm/sysfb/efidrm.c index 3f9cd5d03efb..8b19f437308e 100644 --- a/drivers/gpu/drm/sysfb/efidrm.c +++ b/drivers/gpu/drm/sysfb/efidrm.c @@ -152,6 +152,7 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv, const struct screen_info *si; const struct drm_format_info *format; int width, height, stride; + unsigned int panel_width, panel_height; s64 vsize; u64 mem_flags; struct resource resbuf; @@ -217,6 +218,20 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv, if (drm_edid_header_is_valid(dpy->edid.dummy) == 8) sysfb->edid = dpy->edid.dummy; #endif + + panel_width = width; + panel_height = height; + + if (sysfb->edid) { + const struct drm_edid *drm_edid; + + drm_edid = drm_edid_alloc(sysfb->edid, EDID_LENGTH); + if (drm_edid) { + drm_edid_detect_panel_size(drm_edid, &panel_width, &panel_height); + drm_edid_free(drm_edid); + } + } + sysfb->fb_mode = drm_sysfb_mode(width, height, 0, 0); sysfb->fb_format = format; sysfb->fb_pitch = stride; @@ -340,7 +355,7 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv, drm_connector_helper_add(connector, &efidrm_connector_helper_funcs); drm_connector_set_panel_orientation_with_quirk(connector, DRM_MODE_PANEL_ORIENTATION_UNKNOWN, - width, height); + panel_width, panel_height); if (sysfb->edid) drm_connector_attach_edid_property(connector); diff --git a/drivers/gpu/drm/sysfb/ofdrm.c b/drivers/gpu/drm/sysfb/ofdrm.c index 9d60db45139c..c41255569854 100644 --- a/drivers/gpu/drm/sysfb/ofdrm.c +++ b/drivers/gpu/drm/sysfb/ofdrm.c @@ -229,7 +229,7 @@ static const u8 *display_get_edid_of(struct drm_device *dev, struct device_node { int ret = of_property_read_u8_array(of_node, "EDID", buf, EDID_LENGTH); - if (ret) + if (ret || drm_edid_header_is_valid(buf) != 8) return NULL; return buf; } @@ -828,6 +828,7 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv, enum ofdrm_model model; bool big_endian; int width, height, depth, linebytes; + unsigned int panel_width, panel_height; const struct drm_format_info *format; u64 address; const u8 *edid; @@ -998,6 +999,19 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv, sysfb->fb_gamma_lut_size = OFDRM_GAMMA_LUT_SIZE; sysfb->edid = edid; + panel_width = width; + panel_height = height; + + if (sysfb->edid) { + const struct drm_edid *drm_edid; + + drm_edid = drm_edid_alloc(sysfb->edid, EDID_LENGTH); + if (drm_edid) { + drm_edid_detect_panel_size(drm_edid, &panel_width, &panel_height); + drm_edid_free(drm_edid); + } + } + drm_dbg(dev, "display mode={" DRM_MODE_FMT "}\n", DRM_MODE_ARG(&sysfb->fb_mode)); drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, linebytes=%d byte\n", &format->format, width, height, linebytes); @@ -1069,7 +1083,7 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv, drm_connector_helper_add(connector, &ofdrm_connector_helper_funcs); drm_connector_set_panel_orientation_with_quirk(connector, DRM_MODE_PANEL_ORIENTATION_UNKNOWN, - width, height); + panel_width, panel_height); if (edid) drm_connector_attach_edid_property(connector); diff --git a/drivers/gpu/drm/sysfb/vesadrm.c b/drivers/gpu/drm/sysfb/vesadrm.c index 6a67b2d2e451..f6358a0a68bd 100644 --- a/drivers/gpu/drm/sysfb/vesadrm.c +++ b/drivers/gpu/drm/sysfb/vesadrm.c @@ -402,6 +402,7 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv, const struct screen_info *si; const struct drm_format_info *format; int width, height, stride; + unsigned int panel_width, panel_height; s64 vsize; struct resource resbuf; struct resource *res; @@ -484,6 +485,20 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv, if (drm_edid_header_is_valid(dpy->edid.dummy) == 8) sysfb->edid = dpy->edid.dummy; #endif + + panel_width = width; + panel_height = height; + + if (sysfb->edid) { + const struct drm_edid *drm_edid; + + drm_edid = drm_edid_alloc(sysfb->edid, EDID_LENGTH); + if (drm_edid) { + drm_edid_detect_panel_size(drm_edid, &panel_width, &panel_height); + drm_edid_free(drm_edid); + } + } + sysfb->fb_mode = drm_sysfb_mode(width, height, 0, 0); sysfb->fb_format = format; sysfb->fb_pitch = stride; @@ -585,7 +600,7 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv, drm_connector_helper_add(connector, &vesadrm_connector_helper_funcs); drm_connector_set_panel_orientation_with_quirk(connector, DRM_MODE_PANEL_ORIENTATION_UNKNOWN, - width, height); + panel_width, panel_height); if (sysfb->edid) drm_connector_attach_edid_property(connector); -- 2.55.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v4 3/3] drm/sysfb: Use preferred panel size for panel orientation quirks 2026-09-04 9:07 ` [PATCH v4 3/3] drm/sysfb: Use preferred panel size for panel orientation quirks Thomas Zimmermann @ 2026-09-04 9:41 ` Jani Nikula 2026-09-10 8:11 ` Javier Martinez Canillas 1 sibling, 0 replies; 11+ messages in thread From: Jani Nikula @ 2026-09-04 9:41 UTC (permalink / raw) To: Thomas Zimmermann, javierm, ardb, ilias.apalodimas, maarten.lankhorst, mripard, simona, airlied Cc: dri-devel, linux-efi, sashiko-reviews, Thomas Zimmermann On Fri, 04 Sep 2026, Thomas Zimmermann <tzimmermann@suse.de> wrote: > Sysfb drivers currently use the given display mode for looking up the > panel orientation. But the look-up table stores the native geometry of > the panels, so the lookup fails if the current mode sizes differs. > > Get the panel's native geometry with drm_edid_detect_panel_size() from > the EDID and use it for looking up the panel orientation. > > v2: > - ofdrm: validate EDID header before using it (Sashiko) > > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > Acked-by: Ard Biesheuvel <ardb@kernel.org> Acked-by: Jani Nikula <jani.nikula@intel.com> > --- > drivers/gpu/drm/sysfb/efidrm.c | 17 ++++++++++++++++- > drivers/gpu/drm/sysfb/ofdrm.c | 18 ++++++++++++++++-- > drivers/gpu/drm/sysfb/vesadrm.c | 17 ++++++++++++++++- > 3 files changed, 48 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/sysfb/efidrm.c b/drivers/gpu/drm/sysfb/efidrm.c > index 3f9cd5d03efb..8b19f437308e 100644 > --- a/drivers/gpu/drm/sysfb/efidrm.c > +++ b/drivers/gpu/drm/sysfb/efidrm.c > @@ -152,6 +152,7 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv, > const struct screen_info *si; > const struct drm_format_info *format; > int width, height, stride; > + unsigned int panel_width, panel_height; > s64 vsize; > u64 mem_flags; > struct resource resbuf; > @@ -217,6 +218,20 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv, > if (drm_edid_header_is_valid(dpy->edid.dummy) == 8) > sysfb->edid = dpy->edid.dummy; > #endif > + > + panel_width = width; > + panel_height = height; > + > + if (sysfb->edid) { > + const struct drm_edid *drm_edid; > + > + drm_edid = drm_edid_alloc(sysfb->edid, EDID_LENGTH); > + if (drm_edid) { > + drm_edid_detect_panel_size(drm_edid, &panel_width, &panel_height); > + drm_edid_free(drm_edid); > + } > + } > + > sysfb->fb_mode = drm_sysfb_mode(width, height, 0, 0); > sysfb->fb_format = format; > sysfb->fb_pitch = stride; > @@ -340,7 +355,7 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv, > drm_connector_helper_add(connector, &efidrm_connector_helper_funcs); > drm_connector_set_panel_orientation_with_quirk(connector, > DRM_MODE_PANEL_ORIENTATION_UNKNOWN, > - width, height); > + panel_width, panel_height); > if (sysfb->edid) > drm_connector_attach_edid_property(connector); > > diff --git a/drivers/gpu/drm/sysfb/ofdrm.c b/drivers/gpu/drm/sysfb/ofdrm.c > index 9d60db45139c..c41255569854 100644 > --- a/drivers/gpu/drm/sysfb/ofdrm.c > +++ b/drivers/gpu/drm/sysfb/ofdrm.c > @@ -229,7 +229,7 @@ static const u8 *display_get_edid_of(struct drm_device *dev, struct device_node > { > int ret = of_property_read_u8_array(of_node, "EDID", buf, EDID_LENGTH); > > - if (ret) > + if (ret || drm_edid_header_is_valid(buf) != 8) > return NULL; > return buf; > } > @@ -828,6 +828,7 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv, > enum ofdrm_model model; > bool big_endian; > int width, height, depth, linebytes; > + unsigned int panel_width, panel_height; > const struct drm_format_info *format; > u64 address; > const u8 *edid; > @@ -998,6 +999,19 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv, > sysfb->fb_gamma_lut_size = OFDRM_GAMMA_LUT_SIZE; > sysfb->edid = edid; > > + panel_width = width; > + panel_height = height; > + > + if (sysfb->edid) { > + const struct drm_edid *drm_edid; > + > + drm_edid = drm_edid_alloc(sysfb->edid, EDID_LENGTH); > + if (drm_edid) { > + drm_edid_detect_panel_size(drm_edid, &panel_width, &panel_height); > + drm_edid_free(drm_edid); > + } > + } > + > drm_dbg(dev, "display mode={" DRM_MODE_FMT "}\n", DRM_MODE_ARG(&sysfb->fb_mode)); > drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, linebytes=%d byte\n", > &format->format, width, height, linebytes); > @@ -1069,7 +1083,7 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv, > drm_connector_helper_add(connector, &ofdrm_connector_helper_funcs); > drm_connector_set_panel_orientation_with_quirk(connector, > DRM_MODE_PANEL_ORIENTATION_UNKNOWN, > - width, height); > + panel_width, panel_height); > if (edid) > drm_connector_attach_edid_property(connector); > > diff --git a/drivers/gpu/drm/sysfb/vesadrm.c b/drivers/gpu/drm/sysfb/vesadrm.c > index 6a67b2d2e451..f6358a0a68bd 100644 > --- a/drivers/gpu/drm/sysfb/vesadrm.c > +++ b/drivers/gpu/drm/sysfb/vesadrm.c > @@ -402,6 +402,7 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv, > const struct screen_info *si; > const struct drm_format_info *format; > int width, height, stride; > + unsigned int panel_width, panel_height; > s64 vsize; > struct resource resbuf; > struct resource *res; > @@ -484,6 +485,20 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv, > if (drm_edid_header_is_valid(dpy->edid.dummy) == 8) > sysfb->edid = dpy->edid.dummy; > #endif > + > + panel_width = width; > + panel_height = height; > + > + if (sysfb->edid) { > + const struct drm_edid *drm_edid; > + > + drm_edid = drm_edid_alloc(sysfb->edid, EDID_LENGTH); > + if (drm_edid) { > + drm_edid_detect_panel_size(drm_edid, &panel_width, &panel_height); > + drm_edid_free(drm_edid); > + } > + } > + > sysfb->fb_mode = drm_sysfb_mode(width, height, 0, 0); > sysfb->fb_format = format; > sysfb->fb_pitch = stride; > @@ -585,7 +600,7 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv, > drm_connector_helper_add(connector, &vesadrm_connector_helper_funcs); > drm_connector_set_panel_orientation_with_quirk(connector, > DRM_MODE_PANEL_ORIENTATION_UNKNOWN, > - width, height); > + panel_width, panel_height); > if (sysfb->edid) > drm_connector_attach_edid_property(connector); -- Jani Nikula, Intel ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 3/3] drm/sysfb: Use preferred panel size for panel orientation quirks 2026-09-04 9:07 ` [PATCH v4 3/3] drm/sysfb: Use preferred panel size for panel orientation quirks Thomas Zimmermann 2026-09-04 9:41 ` Jani Nikula @ 2026-09-10 8:11 ` Javier Martinez Canillas 1 sibling, 0 replies; 11+ messages in thread From: Javier Martinez Canillas @ 2026-09-10 8:11 UTC (permalink / raw) To: Thomas Zimmermann, ardb, ilias.apalodimas, jani.nikula, maarten.lankhorst, mripard, simona, airlied Cc: dri-devel, linux-efi, sashiko-reviews, Thomas Zimmermann Thomas Zimmermann <tzimmermann@suse.de> writes: > Sysfb drivers currently use the given display mode for looking up the > panel orientation. But the look-up table stores the native geometry of > the panels, so the lookup fails if the current mode sizes differs. > > Get the panel's native geometry with drm_edid_detect_panel_size() from > the EDID and use it for looking up the panel orientation. > > v2: > - ofdrm: validate EDID header before using it (Sashiko) > > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > Acked-by: Ard Biesheuvel <ardb@kernel.org> > --- Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> -- Best regards, Javier Martinez Canillas Core Platforms Red Hat ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-09-11 7:35 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-09-04 9:06 [PATCH v4 0/3] sysfb: Fix display output on Lenovo D330 (and others) Thomas Zimmermann 2026-09-04 9:07 ` [PATCH v4 1/3] firmware/sysfb: Remove rotation quirk for Lenovo D330 Thomas Zimmermann 2026-09-10 7:23 ` Javier Martinez Canillas 2026-09-10 7:46 ` Thomas Zimmermann 2026-09-04 9:07 ` [PATCH v4 2/3] drm/edid: Add drm_edid_detect_panel_size() Thomas Zimmermann 2026-09-04 9:28 ` Jani Nikula 2026-09-10 8:10 ` Javier Martinez Canillas 2026-09-11 7:35 ` Jani Nikula 2026-09-04 9:07 ` [PATCH v4 3/3] drm/sysfb: Use preferred panel size for panel orientation quirks Thomas Zimmermann 2026-09-04 9:41 ` Jani Nikula 2026-09-10 8:11 ` Javier Martinez Canillas
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).