From: "Màxim Pedraza Padilla" <maximpedraza@gmail.com>
To: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Ard Biesheuvel <ardb@kernel.org>,
Jonathan Corbet <corbet@lwn.net>
Cc: Francesco Valla <francesco@valla.it>,
Mario Limonciello <mario.limonciello@amd.com>,
Javier Martinez Canillas <javierm@redhat.com>,
Jocelyn Falempe <jfalempe@redhat.com>,
Sam Ravnborg <sam@ravnborg.org>,
Ilias Apalodimas <ilias.apalodimas@linaro.org>,
Shuah Khan <skhan@linuxfoundation.org>,
Randy Dunlap <rdunlap@infradead.org>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-efi@vger.kernel.org, linux-doc@vger.kernel.org,
linux-embedded@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH RFC v4 11/13] drm/client: splash: turn the BGRT image on panels mounted turned
Date: Thu, 1 Oct 2026 21:58:45 +0200 [thread overview]
Message-ID: <20261001195847.141192-12-maximpedraza@gmail.com> (raw)
In-Reply-To: <20261001195847.141192-1-maximpedraza@gmail.com>
Since ACPI 6.2, bits 1-2 of the BGRT status tell that the firmware
image is not pre-rotated and how far it has to be turned to show
upright on a panel mounted turned. The client skipped such images
altogether, so tablets and 2-in-1s with a portrait panel got no splash.
Turn the image as the bits say. The values count 90 degree steps
counter clockwise, as Plymouth, the main user of the BGRT, applies
them, and as DRM_MODE_ROTATE_* count, which is what they become.
The offsets need more care. For such an image the firmware gives them
on the upright screen, while the client draws into the buffer as it is
scanned out, which on a panel mounted turned is the upright screen
turned the other way. Check them and apply the efifb sanity check in
the upright frame, then move the image's rectangle into the buffer's
frame. An image without the bits is drawn at its offsets as before:
the buffer is the frame the firmware drew it in, so a pre-rotated image
needs none of the guessing userspace has to do for it.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Màxim Pedraza Padilla <maximpedraza@gmail.com>
---
drivers/gpu/drm/clients/drm_splash.c | 77 ++++++++++++++++++++++++----
1 file changed, 66 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/clients/drm_splash.c b/drivers/gpu/drm/clients/drm_splash.c
index 30ba6573424e..34f3c3910be1 100644
--- a/drivers/gpu/drm/clients/drm_splash.c
+++ b/drivers/gpu/drm/clients/drm_splash.c
@@ -388,14 +388,14 @@ static bool drm_splash_bgrt_available(struct drm_splash *splash)
return false;
}
- if (bgrt_tab.status & ACPI_BGRT_ORIENTATION_OFFSET) {
- drm_info(client->dev, "splash: BGRT rotation bits set, skipping");
- return false;
- }
-
return true;
}
+static inline u8 drm_splash_bgrt_get_status(void)
+{
+ return bgrt_tab.status;
+}
+
static inline unsigned int drm_splash_bgrt_get_xoffset(void)
{
return bgrt_tab.image_offset_x;
@@ -445,6 +445,11 @@ static inline unsigned int drm_splash_bgrt_get_yoffset(void)
return 0;
}
+static inline u8 drm_splash_bgrt_get_status(void)
+{
+ return 0;
+}
+
static inline int drm_splash_bgrt_load(struct drm_splash *splash,
const u8 **data, size_t *size)
{
@@ -452,6 +457,26 @@ static inline int drm_splash_bgrt_load(struct drm_splash *splash,
}
#endif // CONFIG_DRM_CLIENT_SPLASH_SRC_BGRT
+/*
+ * Since ACPI 6.2, bits 1-2 of the BGRT status say that the image is not
+ * pre-rotated for a panel mounted turned, and by how much it has to be
+ * turned to show upright on it: 0, 90, 180 or 270 degrees, which firmware
+ * and userspace (Plymouth) apply counter clockwise, as DRM counts them.
+ */
+static unsigned int drm_splash_bgrt_rotation(void)
+{
+ switch ((drm_splash_bgrt_get_status() & ACPI_BGRT_ORIENTATION_OFFSET) >> 1) {
+ case 1:
+ return DRM_MODE_ROTATE_90;
+ case 2:
+ return DRM_MODE_ROTATE_180;
+ case 3:
+ return DRM_MODE_ROTATE_270;
+ default:
+ return DRM_MODE_ROTATE_0;
+ }
+}
+
static u32 drm_splash_find_usable_format(struct drm_plane *plane,
u32 preferred_format)
{
@@ -709,11 +734,21 @@ static int drm_splash_bmp_to_scanout(struct drm_splash *splash,
}
if (splash->src == DRM_SPLASH_SRC_BGRT) {
- x_pad = drm_splash_bgrt_get_xoffset();
- y_pad = drm_splash_bgrt_get_yoffset();
-
- if ((x_pad + bmp_width) > scanout->width ||
- (y_pad + bmp_height) > scanout->height) {
+ /*
+ * The BGRT offsets place the upright image on the upright
+ * screen, which for a panel mounted turned is not the frame
+ * the buffer is scanned out in. Work in that frame, then move
+ * the image's rectangle into the buffer's.
+ */
+ bool quarter = splash->rotation &
+ (DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_270);
+ unsigned int lw = quarter ? scanout->height : scanout->width;
+ unsigned int lh = quarter ? scanout->width : scanout->height;
+ unsigned int xo = drm_splash_bgrt_get_xoffset();
+ unsigned int yo = drm_splash_bgrt_get_yoffset();
+
+ if (xo > lw || bmp_width > lw - xo ||
+ yo > lh || bmp_height > lh - yo) {
drm_err(client->dev, "splash: BGRT image would overflow");
return -EINVAL;
}
@@ -730,11 +765,30 @@ static int drm_splash_bmp_to_scanout(struct drm_splash *splash,
* the display looking quite bad.
*/
- if (x_pad != (scanout->width - bmp_width) / 2) {
+ if (xo != (lw - bmp_width) / 2) {
drm_err(client->dev, "splash: BGRT sanity check failed");
return -EINVAL;
}
#endif
+
+ switch (splash->rotation) {
+ case DRM_MODE_ROTATE_90:
+ x_pad = yo;
+ y_pad = lw - xo - bmp_width;
+ break;
+ case DRM_MODE_ROTATE_180:
+ x_pad = lw - xo - bmp_width;
+ y_pad = lh - yo - bmp_height;
+ break;
+ case DRM_MODE_ROTATE_270:
+ x_pad = lh - yo - bmp_height;
+ y_pad = xo;
+ break;
+ default:
+ x_pad = xo;
+ y_pad = yo;
+ break;
+ }
} else {
x_pad = drm_splash_place_axis(splash->pos_x, splash->off_x,
scanout->width, img_w);
@@ -818,6 +872,7 @@ static enum drm_splash_source drm_splash_pick_source(struct drm_splash *splash)
/* The BGRT carries no colour: firmware splashes sit on black */
if (drm_splash_bgrt_available(splash)) {
splash->bg_color = CONFIG_DRM_CLIENT_SPLASH_BACKGROUND_COLOR;
+ splash->rotation = drm_splash_bgrt_rotation();
return DRM_SPLASH_SRC_BGRT;
}
--
2.39.5
next prev parent reply other threads:[~2026-10-01 19:59 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-01 19:58 [PATCH RFC v4 00/13] Add splash DRM client Màxim Pedraza Padilla
2026-10-01 19:58 ` [PATCH RFC v4 01/13] drm/clients: Kconfig: indent DRM_CLIENT_DEFAULT with tabs Màxim Pedraza Padilla
2026-10-01 19:58 ` [PATCH RFC v4 02/13] efi: bgrt: export the BGRT table and image size Màxim Pedraza Padilla
2026-10-01 19:58 ` [PATCH RFC v4 03/13] drm: client: add splash client Màxim Pedraza Padilla
2026-10-01 19:58 ` [PATCH RFC v4 04/13] MAINTAINERS: add entry for DRM " Màxim Pedraza Padilla
2026-10-01 19:58 ` [PATCH RFC v4 05/13] drm: docs: remove bootsplash from TODO Màxim Pedraza Padilla
2026-10-01 19:58 ` [PATCH RFC v4 06/13] dt-bindings: display: add a boot logo node under /chosen Màxim Pedraza Padilla
2026-10-01 19:58 ` [PATCH RFC v4 07/13] drm/client: splash: add a device tree image source Màxim Pedraza Padilla
2026-10-01 19:58 ` [PATCH RFC v4 08/13] drm/client: splash: place the device tree image where it asks Màxim Pedraza Padilla
2026-10-01 19:58 ` [PATCH RFC v4 09/13] drm/client: splash: turn the device tree image as " Màxim Pedraza Padilla
2026-10-01 19:58 ` [PATCH RFC v4 10/13] drm/client: splash: take the background colour from the image source Màxim Pedraza Padilla
2026-10-01 19:58 ` Màxim Pedraza Padilla [this message]
2026-10-01 19:58 ` [PATCH RFC v4 12/13] drm/client: splash: prefer what the command line asks for Màxim Pedraza Padilla
2026-10-01 19:58 ` [PATCH RFC v4 13/13] drm/client: splash: document the image sources and parameters Màxim Pedraza Padilla
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261001195847.141192-12-maximpedraza@gmail.com \
--to=maximpedraza@gmail.com \
--cc=airlied@gmail.com \
--cc=ardb@kernel.org \
--cc=conor+dt@kernel.org \
--cc=corbet@lwn.net \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=francesco@valla.it \
--cc=ilias.apalodimas@linaro.org \
--cc=javierm@redhat.com \
--cc=jfalempe@redhat.com \
--cc=krzk+dt@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-efi@vger.kernel.org \
--cc=linux-embedded@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mario.limonciello@amd.com \
--cc=mripard@kernel.org \
--cc=rdunlap@infradead.org \
--cc=robh@kernel.org \
--cc=sam@ravnborg.org \
--cc=simona@ffwll.ch \
--cc=skhan@linuxfoundation.org \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®