From: Thomas Zimmermann <tzimmermann@suse.de>
To: Roshan Kumar <roshaen09@gmail.com>,
linusw@kernel.org, dri-devel@lists.freedesktop.org,
Ze Huang <ze.huang@oss.qualcomm.com>
Cc: leandro.ribeiro@collabora.com, maarten.lankhorst@linux.intel.com,
mripard@kernel.org, airlied@gmail.com, simona@ffwll.ch,
pimyn@google.com, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] drm/pl111: Advertise no pixel blending
Date: Fri, 11 Sep 2026 14:58:34 +0200 [thread overview]
Message-ID: <2684f2f8-d349-4096-b005-b2d040d4cebd@suse.de> (raw)
In-Reply-To: <178906831180.136984.3208749717777263252@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1135 bytes --]
Hi
Am 10.09.26 um 21:25 schrieb Roshan Kumar:
> No physical PL111 hardware here; I tested under QEMU vexpress with
> panic_on_warn, which is also how the syzkaller instance hits this.
Or since you have the system set up already, could you test a patch for
the pl111 driver? It reworks some internals and could use some basic
testing before getting merged. Patch file is attached. Thanks!
Best regards
Thomas
>
> On current master (7.3-rc2) the unpatched driver registers and
> immediately warns: "[PLANE:35:plane-0] pixel format with alpha exposed
> but blend mode not setup", which kills the boot with panic_on_warn.
> With v3 below, the same boot registers pl111 with no warnings at all.
> One note: 860e748bddcc is not in v7.2, so the splat only shows up on
> master/7.3 and later.
>
> v3 also removes the alpha formats from the board-specific tables in
> pl111_versatile.c that the sashiko review caught v2 missing.
--
--
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)
[-- Attachment #2: 0001-drm-pl111-replace-struct-drm_simple_display_pipe-wit.patch --]
[-- Type: text/x-patch, Size: 12098 bytes --]
From fe49e0da40ca703d13c33395b047da9c1ccaa731 Mon Sep 17 00:00:00 2001
From: Ze Huang <ze.huang@oss.qualcomm.com>
Date: Mon, 27 Jul 2026 03:45:17 +0800
Subject: [PATCH] drm/pl111: replace struct drm_simple_display_pipe with
regular atomic helpers
Replace the PL111 simple display pipe with explicit plane, CRTC and
encoder objects.
Move the existing timing, format and pitch validation into explicit
atomic check paths. Use commit-local plane state in the CRTC enable path
when reading framebuffer format state.
Move page-flip event handling to the CRTC commit path.
Signed-off-by: Ze Huang <ze.huang@oss.qualcomm.com>
---
drivers/gpu/drm/pl111/pl111_display.c | 199 +++++++++++++++++++-------
drivers/gpu/drm/pl111/pl111_drm.h | 5 +-
drivers/gpu/drm/pl111/pl111_drv.c | 3 +-
3 files changed, 148 insertions(+), 59 deletions(-)
diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c
index 5d10bc5fdf1f..deac1dee7838 100644
--- a/drivers/gpu/drm/pl111/pl111_display.c
+++ b/drivers/gpu/drm/pl111/pl111_display.c
@@ -15,6 +15,7 @@
#include <linux/media-bus-format.h>
#include <linux/of_graph.h>
+#include <drm/drm_atomic_helper.h>
#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
@@ -37,7 +38,7 @@ irqreturn_t pl111_irq(int irq, void *data)
return IRQ_NONE;
if (irq_stat & CLCD_IRQ_NEXTBASE_UPDATE) {
- drm_crtc_handle_vblank(&priv->pipe.crtc);
+ drm_crtc_handle_vblank(&priv->crtc);
status = IRQ_HANDLED;
}
@@ -49,10 +50,10 @@ irqreturn_t pl111_irq(int irq, void *data)
}
static enum drm_mode_status
-pl111_mode_valid(struct drm_simple_display_pipe *pipe,
- const struct drm_display_mode *mode)
+pl111_crtc_helper_mode_valid(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode)
{
- struct drm_device *drm = pipe->crtc.dev;
+ struct drm_device *drm = crtc->dev;
struct pl111_drm_dev_private *priv = drm->dev_private;
u32 cpp = DIV_ROUND_UP(priv->variant->fb_depth, 8);
u64 bw;
@@ -83,13 +84,34 @@ pl111_mode_valid(struct drm_simple_display_pipe *pipe,
return MODE_OK;
}
-static int pl111_display_check(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *pstate,
- struct drm_crtc_state *cstate)
+static int pl111_plane_helper_atomic_check(struct drm_plane *plane,
+ struct drm_atomic_commit *commit)
{
- const struct drm_display_mode *mode = &cstate->mode;
- struct drm_framebuffer *old_fb = pipe->plane.state->fb;
+ struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(commit, plane);
+ struct drm_plane_state *old_pstate = drm_atomic_get_old_plane_state(commit, plane);
+ struct drm_crtc_state *cstate = NULL;
+ const struct drm_display_mode *mode;
+ struct drm_framebuffer *old_fb = old_pstate->fb;
struct drm_framebuffer *fb = pstate->fb;
+ int ret;
+
+ if (pstate->crtc) {
+ cstate = drm_atomic_get_crtc_state(commit, pstate->crtc);
+ if (IS_ERR(cstate))
+ return PTR_ERR(cstate);
+ }
+
+ ret = drm_atomic_helper_check_plane_state(pstate, cstate,
+ DRM_PLANE_NO_SCALING,
+ DRM_PLANE_NO_SCALING,
+ false, false);
+ if (ret)
+ return ret;
+
+ if (!pstate->visible)
+ return 0;
+
+ mode = &cstate->mode;
if (mode->hdisplay % 16)
return -EINVAL;
@@ -117,16 +139,15 @@ static int pl111_display_check(struct drm_simple_display_pipe *pipe,
return 0;
}
-static void pl111_display_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *cstate,
- struct drm_plane_state *plane_state)
+static void pl111_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_commit *commit)
{
- struct drm_crtc *crtc = &pipe->crtc;
- struct drm_plane *plane = &pipe->plane;
struct drm_device *drm = crtc->dev;
struct pl111_drm_dev_private *priv = drm->dev_private;
+ struct drm_crtc_state *cstate = drm_atomic_get_new_crtc_state(commit, crtc);
+ struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(commit, &priv->plane);
const struct drm_display_mode *mode = &cstate->mode;
- struct drm_framebuffer *fb = plane->state->fb;
+ struct drm_framebuffer *fb = plane_state->fb;
struct drm_connector *connector = priv->connector;
struct drm_bridge *bridge = priv->bridge;
bool grayscale = false;
@@ -355,9 +376,9 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe,
drm_crtc_vblank_on(crtc);
}
-static void pl111_display_disable(struct drm_simple_display_pipe *pipe)
+static void pl111_crtc_helper_atomic_disable(struct drm_crtc *crtc,
+ struct drm_atomic_commit *commit)
{
- struct drm_crtc *crtc = &pipe->crtc;
struct drm_device *drm = crtc->dev;
struct pl111_drm_dev_private *priv = drm->dev_private;
u32 cntl;
@@ -387,38 +408,43 @@ static void pl111_display_disable(struct drm_simple_display_pipe *pipe)
clk_disable_unprepare(priv->clk);
}
-static void pl111_display_update(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *old_pstate)
+static void pl111_plane_helper_atomic_update(struct drm_plane *plane,
+ struct drm_atomic_commit *commit)
{
- struct drm_crtc *crtc = &pipe->crtc;
- struct drm_device *drm = crtc->dev;
+ struct drm_device *drm = plane->dev;
struct pl111_drm_dev_private *priv = drm->dev_private;
- struct drm_pending_vblank_event *event = crtc->state->event;
- struct drm_plane *plane = &pipe->plane;
- struct drm_plane_state *pstate = plane->state;
+ struct drm_plane_state *pstate = drm_atomic_get_new_plane_state(commit, plane);
struct drm_framebuffer *fb = pstate->fb;
- if (fb) {
- u32 addr = drm_fb_dma_get_gem_addr(fb, pstate, 0);
+ if (!fb)
+ return;
- writel(addr, priv->regs + CLCD_UBAS);
- }
+ u32 addr = drm_fb_dma_get_gem_addr(fb, pstate, 0);
- if (event) {
- crtc->state->event = NULL;
+ writel(addr, priv->regs + CLCD_UBAS);
+}
- spin_lock_irq(&crtc->dev->event_lock);
- if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0)
- drm_crtc_arm_vblank_event(crtc, event);
- else
- drm_crtc_send_vblank_event(crtc, event);
- spin_unlock_irq(&crtc->dev->event_lock);
- }
+static void pl111_crtc_helper_atomic_flush(struct drm_crtc *crtc,
+ struct drm_atomic_commit *commit)
+{
+ struct drm_crtc_state *cstate = drm_atomic_get_new_crtc_state(commit, crtc);
+ struct drm_pending_vblank_event *event = cstate->event;
+
+ if (!event)
+ return;
+
+ cstate->event = NULL;
+
+ spin_lock_irq(&crtc->dev->event_lock);
+ if (cstate->active && drm_crtc_vblank_get(crtc) == 0)
+ drm_crtc_arm_vblank_event(crtc, event);
+ else
+ drm_crtc_send_vblank_event(crtc, event);
+ spin_unlock_irq(&crtc->dev->event_lock);
}
-static int pl111_display_enable_vblank(struct drm_simple_display_pipe *pipe)
+static int pl111_display_enable_vblank(struct drm_crtc *crtc)
{
- struct drm_crtc *crtc = &pipe->crtc;
struct drm_device *drm = crtc->dev;
struct pl111_drm_dev_private *priv = drm->dev_private;
@@ -427,21 +453,62 @@ static int pl111_display_enable_vblank(struct drm_simple_display_pipe *pipe)
return 0;
}
-static void pl111_display_disable_vblank(struct drm_simple_display_pipe *pipe)
+static void pl111_display_disable_vblank(struct drm_crtc *crtc)
{
- struct drm_crtc *crtc = &pipe->crtc;
struct drm_device *drm = crtc->dev;
struct pl111_drm_dev_private *priv = drm->dev_private;
writel(0, priv->regs + priv->ienb);
}
-static struct drm_simple_display_pipe_funcs pl111_display_funcs = {
- .mode_valid = pl111_mode_valid,
- .check = pl111_display_check,
- .enable = pl111_display_enable,
- .disable = pl111_display_disable,
- .update = pl111_display_update,
+static int pl111_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_commit *commit)
+{
+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(commit, crtc);
+ int ret;
+
+ if (crtc_state->enable) {
+ ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
+ if (ret)
+ return ret;
+ }
+
+ return drm_atomic_add_affected_planes(commit, crtc);
+}
+
+static struct drm_crtc_funcs pl111_crtc_funcs = {
+ .reset = drm_atomic_helper_crtc_reset,
+ .destroy = drm_crtc_cleanup,
+ .set_config = drm_atomic_helper_set_config,
+ .page_flip = drm_atomic_helper_page_flip,
+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static const struct drm_crtc_helper_funcs pl111_crtc_helper_funcs = {
+ .mode_valid = pl111_crtc_helper_mode_valid,
+ .atomic_check = pl111_crtc_helper_atomic_check,
+ .atomic_enable = pl111_crtc_helper_atomic_enable,
+ .atomic_disable = pl111_crtc_helper_atomic_disable,
+ .atomic_flush = pl111_crtc_helper_atomic_flush,
+};
+
+static const struct drm_plane_funcs pl111_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .reset = drm_atomic_helper_plane_reset,
+ .destroy = drm_plane_cleanup,
+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static const struct drm_plane_helper_funcs pl111_plane_helper_funcs = {
+ .prepare_fb = drm_gem_plane_helper_prepare_fb,
+ .atomic_check = pl111_plane_helper_atomic_check,
+ .atomic_update = pl111_plane_helper_atomic_update,
+};
+
+static const struct drm_encoder_funcs pl111_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
};
static int pl111_clk_div_choose_div(struct clk_hw *hw, unsigned long rate,
@@ -583,18 +650,40 @@ int pl111_display_init(struct drm_device *drm)
return ret;
if (!priv->variant->broken_vblank) {
- pl111_display_funcs.enable_vblank = pl111_display_enable_vblank;
- pl111_display_funcs.disable_vblank = pl111_display_disable_vblank;
+ pl111_crtc_funcs.enable_vblank = pl111_display_enable_vblank;
+ pl111_crtc_funcs.disable_vblank = pl111_display_disable_vblank;
}
- ret = drm_simple_display_pipe_init(drm, &priv->pipe,
- &pl111_display_funcs,
- priv->variant->formats,
- priv->variant->nformats,
- NULL,
- priv->connector);
+ ret = drm_universal_plane_init(drm, &priv->plane, 0,
+ &pl111_plane_funcs,
+ priv->variant->formats,
+ priv->variant->nformats,
+ NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret)
+ return ret;
+
+ drm_plane_helper_add(&priv->plane, &pl111_plane_helper_funcs);
+
+ ret = drm_crtc_init_with_planes(drm, &priv->crtc, &priv->plane,
+ NULL, &pl111_crtc_funcs, NULL);
+ if (ret)
+ return ret;
+
+ drm_crtc_helper_add(&priv->crtc, &pl111_crtc_helper_funcs);
+
+ ret = drm_encoder_init(drm, &priv->encoder, &pl111_encoder_funcs,
+ DRM_MODE_ENCODER_NONE, NULL);
if (ret)
return ret;
+ priv->encoder.possible_crtcs = drm_crtc_mask(&priv->crtc);
+
+ if (priv->connector) {
+ ret = drm_connector_attach_encoder(priv->connector,
+ &priv->encoder);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h
index d1fe756444ee..ec92a5a180a8 100644
--- a/drivers/gpu/drm/pl111/pl111_drm.h
+++ b/drivers/gpu/drm/pl111/pl111_drm.h
@@ -21,7 +21,6 @@
#include <drm/drm_encoder.h>
#include <drm/drm_gem.h>
#include <drm/drm_panel.h>
-#include <drm/drm_simple_kms_helper.h>
/*
* CLCD Controller Internal Register addresses
@@ -135,7 +134,9 @@ struct pl111_drm_dev_private {
struct drm_connector *connector;
struct drm_panel *panel;
struct drm_bridge *bridge;
- struct drm_simple_display_pipe pipe;
+ struct drm_plane plane;
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
void *regs;
u32 memory_bw;
diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c
index 8ec659b3c08e..e83eb95c8414 100644
--- a/drivers/gpu/drm/pl111/pl111_drv.c
+++ b/drivers/gpu/drm/pl111/pl111_drv.c
@@ -169,8 +169,7 @@ static int pl111_modeset_init(struct drm_device *dev)
goto out_bridge;
}
- ret = drm_simple_display_pipe_attach_bridge(&priv->pipe,
- bridge);
+ ret = drm_bridge_attach(&priv->encoder, bridge, NULL, 0);
if (ret)
return ret;
--
2.55.0
next prev parent reply other threads:[~2026-09-11 12:58 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-25 10:54 Roshan Kumar
2026-09-08 21:31 ` Leandro Ribeiro
2026-09-09 4:17 ` Roshan Kumar
2026-09-09 8:16 ` Thomas Zimmermann
2026-09-11 13:24 ` Linus Walleij
2026-09-11 13:26 ` Linus Walleij
[not found] ` <d3a928e0-0faa-4cd4-9d2e-cb9be4cf84c0@suse.de>
2026-09-10 5:44 ` Roshan Kumar
2026-09-10 5:45 ` [PATCH v2] drm/pl111: drop alpha formats the hardware cannot scan out Roshan Kumar
2026-09-10 6:15 ` Thomas Zimmermann
2026-09-10 19:25 ` [PATCH] drm/pl111: Advertise no pixel blending Roshan Kumar
2026-09-11 6:33 ` Thomas Zimmermann
2026-09-11 12:58 ` Thomas Zimmermann [this message]
2026-09-10 19:25 ` [PATCH v3] drm/pl111: drop alpha formats the hardware cannot scan out Roshan Kumar
2026-09-11 6:41 ` Thomas Zimmermann
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=2684f2f8-d349-4096-b005-b2d040d4cebd@suse.de \
--to=tzimmermann@suse.de \
--cc=airlied@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=leandro.ribeiro@collabora.com \
--cc=linusw@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=pimyn@google.com \
--cc=roshaen09@gmail.com \
--cc=simona@ffwll.ch \
--cc=ze.huang@oss.qualcomm.com \
/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®