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>, Helge Deller <deller@gmx.de>,
Peter Jones <pjones@redhat.com>
Cc: Francesco Valla <francesco@valla.it>,
Jani Nikula <jani.nikula@linux.intel.com>,
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-fbdev@vger.kernel.org,
linux-doc@vger.kernel.org, linux-embedded@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH v6 09/15] drm/client: splash: add a device tree image source
Date: Tue, 27 Oct 2026 14:53:36 +0100 [thread overview]
Message-ID: <20261027135342.2003632-10-maximpedraza@gmail.com> (raw)
In-Reply-To: <20261027135342.2003632-1-maximpedraza@gmail.com>
Embedded products often share one kernel image and one board support
package across several models that differ in branding. The splash
client can show the firmware's BGRT image or a BMP loaded as firmware,
but a device tree system has no BGRT, and a BMP loaded as firmware is
either built into the kernel, which means one kernel per logo, or read
from a filesystem that is not there yet when the display comes up. With
U-Boot's Falcon mode the SPL starts the kernel directly, and the device
tree is the only thing that reaches it.
Add a source that takes the image from a "boot-logo" node under /chosen.
The BMP either sits in the node itself, in a "logo-image" property that
dtc fills in with /incbin/, or in a reserved memory region the
bootloader loaded it into, named by "memory-region". Exactly one of the
two must be present; a node with both or neither is ignored with a
warning.
The image in the node is used where it is, with nothing to copy; the
client holds the node, or keeps the region mapped, for as long as it is
there, so that an output plugged in later gets the image too. The region
is mapped like the BGRT image, and the BMP header is checked against its
size. The image is found when the source is picked: a node whose image
cannot be had, because its region does not resolve or cannot be mapped,
or because reading a region takes CONFIG_OF_RESERVED_MEM and it is not
there, is skipped with a warning, so that the other sources still get
their turn.
A node is only there if someone put it there for that board, so the
device tree goes first, then the BGRT, then the BMP loaded as firmware.
The source is built with CONFIG_DRM_CLIENT_SPLASH_SRC_DT, which needs
CONFIG_OF.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Màxim Pedraza Padilla <maximpedraza@gmail.com>
---
drivers/gpu/drm/clients/Kconfig | 15 +++
drivers/gpu/drm/clients/drm_splash.c | 142 ++++++++++++++++++++++++++-
2 files changed, 154 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/clients/Kconfig b/drivers/gpu/drm/clients/Kconfig
index 51ae6c6bd89b..172781bbc2d7 100644
--- a/drivers/gpu/drm/clients/Kconfig
+++ b/drivers/gpu/drm/clients/Kconfig
@@ -106,6 +106,21 @@ config DRM_CLIENT_SPLASH_BACKGROUND_COLOR
help
The splash background color, in RGB888 format.
+config DRM_CLIENT_SPLASH_SRC_DT
+ bool "Device tree as splash source"
+ depends on DRM_CLIENT_SPLASH
+ depends on OF
+ select DRM_CLIENT_SPLASH_BMP_SUPPORT
+ help
+ Use a BMP image described by a node compatible with "boot-logo"
+ under /chosen in the device tree, either carried in the node itself
+ or placed by the bootloader in a reserved memory region. This lets
+ one kernel image show a different logo on each board or product,
+ chosen by the device tree it boots with.
+
+ When present, the device tree image is preferred over the other
+ sources.
+
config DRM_CLIENT_SPLASH_SRC_BGRT
bool "EFI BGRT as splash source"
depends on DRM_CLIENT_SPLASH
diff --git a/drivers/gpu/drm/clients/drm_splash.c b/drivers/gpu/drm/clients/drm_splash.c
index 911149b92a52..618c060f33d5 100644
--- a/drivers/gpu/drm/clients/drm_splash.c
+++ b/drivers/gpu/drm/clients/drm_splash.c
@@ -8,9 +8,12 @@
#include <linux/efi-bgrt.h>
#include <linux/firmware.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <linux/iosys-map.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_reserved_mem.h>
#include <linux/overflow.h>
#include <linux/slab.h>
#include <linux/types.h>
@@ -45,6 +48,7 @@
*/
enum drm_splash_source {
DRM_SPLASH_SRC_NONE,
+ DRM_SPLASH_SRC_DT,
DRM_SPLASH_SRC_BGRT,
DRM_SPLASH_SRC_BMP,
};
@@ -96,6 +100,10 @@ struct drm_splash {
*/
const struct firmware *fw;
void *map_data;
+ /* The device tree node, and where in it or in its region the image is */
+ struct device_node *dt_np;
+ const u8 *dt_data;
+ size_t dt_len;
enum drm_splash_source src;
};
@@ -185,6 +193,127 @@ static int drm_splash_fw_request_bmp(struct drm_splash *splash)
}
#endif // CONFIG_DRM_CLIENT_SPLASH_SRC_BMP
+#if IS_ENABLED(CONFIG_DRM_CLIENT_SPLASH_SRC_DT)
+#define DRM_SPLASH_DT_COMPATIBLE "boot-logo"
+
+/*
+ * The boot logo node, if the device tree has a usable one. Only a child of
+ * /chosen is considered, not anything compatible anywhere in the tree: the
+ * image is configuration handed over by the firmware, not a device.
+ */
+static struct device_node *drm_splash_dt_node(struct drm_splash *splash)
+{
+ struct drm_client_dev *client = &splash->client;
+ struct device_node *np;
+ bool image, region;
+
+ np = of_get_compatible_child(of_chosen, DRM_SPLASH_DT_COMPATIBLE);
+ if (!np)
+ return NULL;
+
+ if (!of_device_is_available(np))
+ goto out_put;
+
+ image = of_property_present(np, "logo-image");
+ region = of_property_present(np, "memory-region");
+ if (image == region) {
+ drm_warn(client->dev,
+ "splash: %pOF needs exactly one of logo-image or memory-region\n",
+ np);
+ goto out_put;
+ }
+
+ /* Without it the region can never be read: let the other sources go */
+ if (region && !IS_ENABLED(CONFIG_OF_RESERVED_MEM)) {
+ drm_warn(client->dev,
+ "splash: %pOF needs CONFIG_OF_RESERVED_MEM for memory-region\n",
+ np);
+ goto out_put;
+ }
+
+ return np;
+
+out_put:
+ of_node_put(np);
+ return NULL;
+}
+
+/*
+ * Find the image when the source is picked, and keep it for the outputs
+ * plugged in later. A node whose image cannot be had leaves the other
+ * sources their turn.
+ */
+static bool drm_splash_dt_open(struct drm_splash *splash)
+{
+ struct drm_client_dev *client = &splash->client;
+ struct device_node *np;
+ struct resource res;
+ const void *prop;
+ int len, ret;
+
+ np = drm_splash_dt_node(splash);
+ if (!np)
+ return false;
+
+ /*
+ * An image in the node is used in place, with nothing to copy: the
+ * node is held until the image is cleaned up.
+ */
+ prop = of_get_property(np, "logo-image", &len);
+ if (prop) {
+ splash->dt_data = prop;
+ splash->dt_len = len;
+ goto out_keep;
+ }
+
+ /* Otherwise the bootloader loaded it into a reserved region */
+ ret = of_reserved_mem_region_to_resource(np, 0, &res);
+ if (ret) {
+ drm_warn(client->dev, "splash: %pOF: no usable memory-region: %d\n",
+ np, ret);
+ goto out_put;
+ }
+
+ splash->map_data = memremap(res.start, resource_size(&res),
+ MEMREMAP_WB);
+ if (!splash->map_data) {
+ drm_warn(client->dev, "splash: failed to map %pR\n", &res);
+ goto out_put;
+ }
+
+ /* The BMP header, checked against this size, says how much is image */
+ splash->dt_data = splash->map_data;
+ splash->dt_len = resource_size(&res);
+
+out_keep:
+ splash->dt_np = np;
+ return true;
+
+out_put:
+ of_node_put(np);
+ return false;
+}
+
+static int drm_splash_dt_load(struct drm_splash *splash, const u8 **data,
+ size_t *size)
+{
+ *data = splash->dt_data;
+ *size = splash->dt_len;
+ return 0;
+}
+#else
+static bool drm_splash_dt_open(struct drm_splash *splash)
+{
+ return false;
+}
+
+static int drm_splash_dt_load(struct drm_splash *splash,
+ const u8 **data, size_t *size)
+{
+ return -EOPNOTSUPP;
+}
+#endif // CONFIG_DRM_CLIENT_SPLASH_SRC_DT
+
static bool drm_splash_bgrt_available(struct drm_splash *splash)
{
struct drm_client_dev *client = &splash->client;
@@ -509,6 +638,8 @@ static int drm_splash_image_load(struct drm_splash *splash, const u8 **img_data,
size_t *img_data_len)
{
switch (splash->src) {
+ case DRM_SPLASH_SRC_DT:
+ return drm_splash_dt_load(splash, img_data, img_data_len);
case DRM_SPLASH_SRC_BGRT:
return drm_splash_bgrt_load(splash, img_data, img_data_len);
case DRM_SPLASH_SRC_BMP:
@@ -521,12 +652,15 @@ static int drm_splash_image_load(struct drm_splash *splash, const u8 **img_data,
}
/*
- * Pick the one source the image will come from: the BGRT is whatever the
- * firmware shows, and the BMP loaded as firmware is the fallback. With
- * neither, only the background colour is drawn.
+ * Pick the one source the image will come from. A device tree node is only
+ * there if someone put it there for this board, so it goes first; the BGRT
+ * is whatever the firmware shows, and the BMP loaded as firmware is the
+ * fallback. With none of them, only the background colour is drawn.
*/
static enum drm_splash_source drm_splash_pick_source(struct drm_splash *splash)
{
+ if (drm_splash_dt_open(splash))
+ return DRM_SPLASH_SRC_DT;
if (drm_splash_bgrt_available(splash))
return DRM_SPLASH_SRC_BGRT;
if (IS_ENABLED(CONFIG_DRM_CLIENT_SPLASH_SRC_BMP))
@@ -540,6 +674,8 @@ static void drm_splash_image_cleanup(struct drm_splash *splash)
{
memunmap(splash->map_data);
splash->map_data = NULL;
+ of_node_put(splash->dt_np);
+ splash->dt_np = NULL;
release_firmware(splash->fw);
splash->fw = NULL;
}
--
2.39.5
next prev parent reply other threads:[~2026-10-27 13:54 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-27 13:53 [PATCH v6 00/15] Add splash DRM client Màxim Pedraza Padilla
2026-10-27 13:53 ` [PATCH v6 01/15] drm/clients: Kconfig: indent DRM_CLIENT_DEFAULT with tabs Màxim Pedraza Padilla
2026-10-27 13:53 ` [PATCH v6 02/15] efi: bgrt: add accessors for the boot graphics Màxim Pedraza Padilla
2026-10-27 13:53 ` [PATCH v6 03/15] fbdev: efifb: move the BMP headers to <video/bmp.h> Màxim Pedraza Padilla
2026-10-27 13:53 ` [PATCH v6 04/15] drm: client: add splash client Màxim Pedraza Padilla
2026-10-27 13:53 ` [PATCH v6 05/15] MAINTAINERS: add entry for DRM " Màxim Pedraza Padilla
2026-10-27 13:53 ` [PATCH v6 06/15] drm: docs: remove bootsplash from TODO Màxim Pedraza Padilla
2026-10-27 13:53 ` [PATCH v6 07/15] dt-bindings: display: add a boot logo node under /chosen Màxim Pedraza Padilla
2026-10-27 18:59 ` Rob Herring (Arm)
2026-10-27 13:53 ` [PATCH v6 08/15] drm/client: splash: pick the image source in one place Màxim Pedraza Padilla
2026-10-27 13:53 ` Màxim Pedraza Padilla [this message]
2026-10-27 13:53 ` [PATCH v6 10/15] drm/client: splash: place the device tree image where it asks Màxim Pedraza Padilla
2026-10-27 13:53 ` [PATCH v6 11/15] drm/client: splash: turn the device tree image as " Màxim Pedraza Padilla
2026-10-27 13:53 ` [PATCH v6 12/15] drm/client: splash: take the background colour from the image source Màxim Pedraza Padilla
2026-10-27 13:53 ` [PATCH v6 13/15] drm/client: splash: turn the BGRT image on panels mounted turned Màxim Pedraza Padilla
2026-10-27 13:53 ` [PATCH v6 14/15] drm/client: splash: follow the connector's orientation Màxim Pedraza Padilla
2026-10-27 13:53 ` [PATCH v6 15/15] drm/client: splash: document the image sources 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=20261027135342.2003632-10-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=deller@gmx.de \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=francesco@valla.it \
--cc=ilias.apalodimas@linaro.org \
--cc=jani.nikula@linux.intel.com \
--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-fbdev@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=pjones@redhat.com \
--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