dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/2] drm/mipi-dbi: display a cropped region of an oversized framebuffer
@ 2026-09-10 18:48 Jonathan Frazin
  2026-09-10 18:48 ` [PATCH v1 1/2] drm/mipi-dbi: honour the plane source offset when flushing Jonathan Frazin
  2026-09-10 18:48 ` [PATCH v1 2/2] drm/tiny: allow a framebuffer larger than the panel on MIPI DBI drivers Jonathan Frazin
  0 siblings, 2 replies; 6+ messages in thread
From: Jonathan Frazin @ 2026-09-10 18:48 UTC (permalink / raw)
  To: dri-devel
  Cc: Thomas Zimmermann, Maxime Ripard, Maarten Lankhorst, David Airlie,
	Simona Vetter, Kamlesh Gurudasani, Alex Lanzano, linux-kernel,
	Jonathan Frazin

A drm/tiny MIPI DBI panel can currently only scan out a framebuffer that
is exactly panel-sized, always from the origin. This series lets a client
allocate a larger framebuffer and choose the displayed region via the
plane source rectangle - a crop / pan with no scaling.

Motivation: feeding hardware-decoded video to a small SPI panel. The
video decoder emits a fixed frame size; being able to point the panel at
a panel-sized window of that buffer avoids a full-frame CPU copy on every
flush and lets userspace pan/centre the image.

Patch 1 is the actual fix - mipi_dbi_fb_dirty() addressed the controller
in framebuffer coordinates, which is only correct while src_x/src_y are
zero. It now subtracts the plane source origin.

Patch 2 raises mode_config.max_width/height (pinned to the panel size) on
the six drm/tiny drivers that flush through the shared
drm_mipi_dbi_plane_helper_atomic_update(). ili9225 is excluded - it has
its own flush path that does not carry the source offset.

Open question for patch 2: the six drivers each set the limits identically
in their probe. This could instead be a shared helper (or folded into
drm_mipi_dbi_dev_init / the DRM_MIPI_DBI_MODE_CONFIG_* macros) so future
drivers get it for free. Happy to respin that way if preferred - the
per-driver form is what is shown here because it is the smaller diff and
easier to review a first pass.

The min_width/min_height, the fixed mode, the connector and the
mode-sized transfer buffer are all unchanged, and
drm_mipi_dbi_plane_helper_atomic_check() still enforces DRM_PLANE_NO_SCALING
and no repositioning, so the flushed rectangle stays bounded by the panel
regardless of the framebuffer dimensions.

Tested on hardware: ILI9341 and ST7789V (through panel-mipi-dbi), both
240x320 - an oversized framebuffer is accepted and a non-zero-offset
panel-sized window scans out correctly; a panel-sized framebuffer is
unchanged. HX8357D was tested during the downstream review by Dave
Stevenson (Cc'd). ili9486, mi0283qt and ili9163 are build-tested only.

Both patches have been carried in the Raspberry Pi kernel (rpi-7.2.y) and
in use there:
https://github.com/raspberrypi/linux/pull/7589

Applies to current mainline / drm-misc-next; the touched files are
identical there.

Jonathan Frazin (2):
  drm/mipi-dbi: honour the plane source offset when flushing
  drm/tiny: allow a framebuffer larger than the panel on MIPI DBI
    drivers

 drivers/gpu/drm/drm_mipi_dbi.c        | 14 +++++++++++---
 drivers/gpu/drm/tiny/hx8357d.c        |  8 ++++++--
 drivers/gpu/drm/tiny/ili9163.c        |  8 ++++++--
 drivers/gpu/drm/tiny/ili9341.c        |  8 ++++++--
 drivers/gpu/drm/tiny/ili9486.c        |  8 ++++++--
 drivers/gpu/drm/tiny/mi0283qt.c       |  8 ++++++--
 drivers/gpu/drm/tiny/panel-mipi-dbi.c |  8 ++++++--
 7 files changed, 47 insertions(+), 15 deletions(-)

-- 
2.53.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v1 1/2] drm/mipi-dbi: honour the plane source offset when flushing
  2026-09-10 18:48 [PATCH v1 0/2] drm/mipi-dbi: display a cropped region of an oversized framebuffer Jonathan Frazin
@ 2026-09-10 18:48 ` Jonathan Frazin
  2026-09-10 19:07   ` sashiko-bot
  2026-09-10 18:48 ` [PATCH v1 2/2] drm/tiny: allow a framebuffer larger than the panel on MIPI DBI drivers Jonathan Frazin
  1 sibling, 1 reply; 6+ messages in thread
From: Jonathan Frazin @ 2026-09-10 18:48 UTC (permalink / raw)
  To: dri-devel
  Cc: Thomas Zimmermann, Maxime Ripard, Maarten Lankhorst, David Airlie,
	Simona Vetter, Kamlesh Gurudasani, Alex Lanzano, linux-kernel,
	Jonathan Frazin, Dave Stevenson

mipi_dbi_fb_dirty() takes the damage rectangle from
drm_atomic_helper_damage_merged(), which is expressed in framebuffer
coordinates and already clipped to the plane's source rectangle.  It
then passed that rectangle straight to mipi_dbi_set_window_address(),
which is correct only while the source rectangle starts at (0,0) - i.e.
while the framebuffer is exactly panel-sized.

If a driver allows a framebuffer larger than the panel and the plane
selects a sub-region with a non-zero src_x/src_y, the controller was
still addressed in framebuffer coordinates, so the wrong part of the
panel was written and an out-of-range window could be programmed.

Pass the integer plane source origin down to mipi_dbi_fb_dirty() and
subtract it when programming the column/page address.  The copy into the
transfer buffer still uses the framebuffer-coordinate rectangle, so it
keeps reading the correct pixels from an oversized source.  With a
panel-sized framebuffer src_x/src_y are zero and behaviour is unchanged.

Cc: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Jonathan Frazin <frazinjonathan@gmail.com>
---
 drivers/gpu/drm/drm_mipi_dbi.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index 25cf04d02..38db45a9d 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -271,7 +271,8 @@ static void mipi_dbi_set_window_address(struct mipi_dbi_dev *dbidev,
 }
 
 static void mipi_dbi_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb,
-			      struct drm_rect *rect, struct drm_format_conv_state *fmtcnv_state)
+			      struct drm_rect *rect, unsigned int src_x, unsigned int src_y,
+			      struct drm_format_conv_state *fmtcnv_state)
 {
 	struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
 	unsigned int height = rect->y2 - rect->y1;
@@ -298,8 +299,13 @@ static void mipi_dbi_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb,
 		tr = src->vaddr; /* TODO: Use mapping abstraction properly */
 	}
 
-	mipi_dbi_set_window_address(dbidev, rect->x1, rect->x2 - 1, rect->y1,
-				    rect->y2 - 1);
+	/*
+	 * @rect is in framebuffer coordinates and has been clipped to the plane
+	 * src rectangle by the damage iterator. The panel is addressed relative
+	 * to the src origin, so subtract it here.
+	 */
+	mipi_dbi_set_window_address(dbidev, rect->x1 - src_x, rect->x2 - 1 - src_x,
+				    rect->y1 - src_y, rect->y2 - 1 - src_y);
 
 	if (fb->format->format == DRM_FORMAT_XRGB8888)
 		dst_format = drm_format_info(dbidev->pixel_format);
@@ -390,6 +396,8 @@ void drm_mipi_dbi_plane_helper_atomic_update(struct drm_plane *plane,
 	if (drm_dev_enter(plane->dev, &idx)) {
 		if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &rect))
 			mipi_dbi_fb_dirty(&shadow_plane_state->data[0], fb, &rect,
+					  plane_state->src_x >> 16,
+					  plane_state->src_y >> 16,
 					  &shadow_plane_state->fmtcnv_state);
 		drm_dev_exit(idx);
 	}
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v1 2/2] drm/tiny: allow a framebuffer larger than the panel on MIPI DBI drivers
  2026-09-10 18:48 [PATCH v1 0/2] drm/mipi-dbi: display a cropped region of an oversized framebuffer Jonathan Frazin
  2026-09-10 18:48 ` [PATCH v1 1/2] drm/mipi-dbi: honour the plane source offset when flushing Jonathan Frazin
@ 2026-09-10 18:48 ` Jonathan Frazin
  2026-09-10 19:05   ` sashiko-bot
  1 sibling, 1 reply; 6+ messages in thread
From: Jonathan Frazin @ 2026-09-10 18:48 UTC (permalink / raw)
  To: dri-devel
  Cc: Thomas Zimmermann, Maxime Ripard, Maarten Lankhorst, David Airlie,
	Simona Vetter, Kamlesh Gurudasani, Alex Lanzano, linux-kernel,
	Jonathan Frazin, Dave Stevenson

Every drm/tiny MIPI DBI driver pins mode_config.max_width/max_height to
the panel size, so KMS rejects any framebuffer that is not exactly
panel-sized:

    ili9341 spi0.0: bad framebuffer width 480, should be >= 240 && <= 240

Raise the maximums to DRM_SHADOW_PLANE_MAX_WIDTH/HEIGHT (which its
kerneldoc recommends for shadow-plane drivers) on the drivers that flush
through the shared drm_mipi_dbi_plane_helper_atomic_update(), so a client
can allocate a larger framebuffer and pick the displayed region through
the plane source rectangle - a crop / pan with no scaling, now that
drm_mipi_dbi honours the source offset (previous patch):

    ili9341, hx8357d, ili9486, mi0283qt, ili9163, panel-mipi-dbi

The fixed mode, the minimums and the connector are unchanged. The plane
check (drm_mipi_dbi_plane_helper_atomic_check) still forbids scaling and
repositioning, and the transfer buffer is sized from the display mode,
so the flushed rectangle stays bounded by the panel regardless of the
framebuffer dimensions.

ili9225 is left out: it has its own atomic_update / ili9225_fb_dirty()
that addresses the panel from the damage rectangle without the source
offset, so raising its limits would let a mispositioned buffer through.

Cc: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Jonathan Frazin <frazinjonathan@gmail.com>
---
 drivers/gpu/drm/tiny/hx8357d.c        | 8 ++++++--
 drivers/gpu/drm/tiny/ili9163.c        | 8 ++++++--
 drivers/gpu/drm/tiny/ili9341.c        | 8 ++++++--
 drivers/gpu/drm/tiny/ili9486.c        | 8 ++++++--
 drivers/gpu/drm/tiny/mi0283qt.c       | 8 ++++++--
 drivers/gpu/drm/tiny/panel-mipi-dbi.c | 8 ++++++--
 6 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c
index f942a8d09..0599b8ccf 100644
--- a/drivers/gpu/drm/tiny/hx8357d.c
+++ b/drivers/gpu/drm/tiny/hx8357d.c
@@ -320,9 +320,13 @@ static int hx8357d_probe(struct spi_device *spi)
 		return ret;
 
 	drm->mode_config.min_width = dbidev->mode.hdisplay;
-	drm->mode_config.max_width = dbidev->mode.hdisplay;
+	/*
+	 * Allow a framebuffer larger than the panel so a sub-region can be
+	 * displayed via the plane source rectangle (crop / pan, no scaling).
+	 */
+	drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
 	drm->mode_config.min_height = dbidev->mode.vdisplay;
-	drm->mode_config.max_height = dbidev->mode.vdisplay;
+	drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
 	drm->mode_config.funcs = &hx8357d_mode_config_funcs;
 	drm->mode_config.preferred_depth = 16;
 	drm->mode_config.helper_private = &hx8357d_mode_config_helper_funcs;
diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c
index 884242450..fe6c13056 100644
--- a/drivers/gpu/drm/tiny/ili9163.c
+++ b/drivers/gpu/drm/tiny/ili9163.c
@@ -251,9 +251,13 @@ static int ili9163_probe(struct spi_device *spi)
 		return ret;
 
 	drm->mode_config.min_width = dbidev->mode.hdisplay;
-	drm->mode_config.max_width = dbidev->mode.hdisplay;
+	/*
+	 * Allow a framebuffer larger than the panel so a sub-region can be
+	 * displayed via the plane source rectangle (crop / pan, no scaling).
+	 */
+	drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
 	drm->mode_config.min_height = dbidev->mode.vdisplay;
-	drm->mode_config.max_height = dbidev->mode.vdisplay;
+	drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
 	drm->mode_config.funcs = &ili9163_mode_config_funcs;
 	drm->mode_config.preferred_depth = 16;
 	drm->mode_config.helper_private = &ili9163_mode_config_helper_funcs;
diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c
index 003381aa2..1e4bb56e3 100644
--- a/drivers/gpu/drm/tiny/ili9341.c
+++ b/drivers/gpu/drm/tiny/ili9341.c
@@ -282,9 +282,13 @@ static int ili9341_probe(struct spi_device *spi)
 		return ret;
 
 	drm->mode_config.min_width = dbidev->mode.hdisplay;
-	drm->mode_config.max_width = dbidev->mode.hdisplay;
+	/*
+	 * Allow a framebuffer larger than the panel so a sub-region can be
+	 * displayed via the plane source rectangle (crop / pan, no scaling).
+	 */
+	drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
 	drm->mode_config.min_height = dbidev->mode.vdisplay;
-	drm->mode_config.max_height = dbidev->mode.vdisplay;
+	drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
 	drm->mode_config.funcs = &ili9341_mode_config_funcs;
 	drm->mode_config.preferred_depth = 16;
 	drm->mode_config.helper_private = &ili9341_mode_config_helper_funcs;
diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c
index fab8bd7ce..de33d702a 100644
--- a/drivers/gpu/drm/tiny/ili9486.c
+++ b/drivers/gpu/drm/tiny/ili9486.c
@@ -309,9 +309,13 @@ static int ili9486_probe(struct spi_device *spi)
 		return ret;
 
 	drm->mode_config.min_width = dbidev->mode.hdisplay;
-	drm->mode_config.max_width = dbidev->mode.hdisplay;
+	/*
+	 * Allow a framebuffer larger than the panel so a sub-region can be
+	 * displayed via the plane source rectangle (crop / pan, no scaling).
+	 */
+	drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
 	drm->mode_config.min_height = dbidev->mode.vdisplay;
-	drm->mode_config.max_height = dbidev->mode.vdisplay;
+	drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
 	drm->mode_config.funcs = &ili9486_mode_config_funcs;
 	drm->mode_config.preferred_depth = 16;
 	drm->mode_config.helper_private = &ili9486_mode_config_helper_funcs;
diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c
index b0121e89e..df3801914 100644
--- a/drivers/gpu/drm/tiny/mi0283qt.c
+++ b/drivers/gpu/drm/tiny/mi0283qt.c
@@ -290,9 +290,13 @@ static int mi0283qt_probe(struct spi_device *spi)
 		return ret;
 
 	drm->mode_config.min_width = dbidev->mode.hdisplay;
-	drm->mode_config.max_width = dbidev->mode.hdisplay;
+	/*
+	 * Allow a framebuffer larger than the panel so a sub-region can be
+	 * displayed via the plane source rectangle (crop / pan, no scaling).
+	 */
+	drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
 	drm->mode_config.min_height = dbidev->mode.vdisplay;
-	drm->mode_config.max_height = dbidev->mode.vdisplay;
+	drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
 	drm->mode_config.funcs = &mi0283qt_mode_config_funcs;
 	drm->mode_config.preferred_depth = 16;
 	drm->mode_config.helper_private = &mi0283qt_mode_config_helper_funcs;
diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
index 60cd65cae..a0a098b0d 100644
--- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c
+++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
@@ -448,9 +448,13 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
 		return ret;
 
 	drm->mode_config.min_width = dbidev->mode.hdisplay;
-	drm->mode_config.max_width = dbidev->mode.hdisplay;
+	/*
+	 * Allow a framebuffer larger than the panel so a sub-region can be
+	 * displayed via the plane source rectangle (crop / pan, no scaling).
+	 */
+	drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;
 	drm->mode_config.min_height = dbidev->mode.vdisplay;
-	drm->mode_config.max_height = dbidev->mode.vdisplay;
+	drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
 	drm->mode_config.funcs = &panel_mipi_dbi_mode_config_funcs;
 	drm->mode_config.preferred_depth = bpp;
 	drm->mode_config.helper_private = &panel_mipi_dbi_mode_config_helper_funcs;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v1 2/2] drm/tiny: allow a framebuffer larger than the panel on MIPI DBI drivers
  2026-09-10 18:48 ` [PATCH v1 2/2] drm/tiny: allow a framebuffer larger than the panel on MIPI DBI drivers Jonathan Frazin
@ 2026-09-10 19:05   ` sashiko-bot
  2026-09-11  0:19     ` Jonathan Frazin
  0 siblings, 1 reply; 6+ messages in thread
From: sashiko-bot @ 2026-09-10 19:05 UTC (permalink / raw)
  To: Jonathan Frazin; +Cc: dri-devel

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] Heap buffer overflow in MIPI DBI transmit buffer due to fractional source coordinates.
--

commit 4a10bf379a1886aa47defe01dc700836d3b28773
Author: Jonathan Frazin <frazinjonathan@gmail.com>

drm/tiny: allow a framebuffer larger than the panel on MIPI DBI drivers

This commit raises the max_width and max_height for several MIPI DBI
drivers to DRM_SHADOW_PLANE_MAX_WIDTH/HEIGHT. This allows userspace to
allocate larger framebuffers and use the plane source rectangle to
pan without scaling.

> diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
> index 60cd65cae41d8..a0a098b0da8a3 100644
> --- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c
> +++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
[ ... ]
> @@ -448,9 +448,13 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
>  		return ret;
>  
>  	drm->mode_config.min_width = dbidev->mode.hdisplay;
> -	drm->mode_config.max_width = dbidev->mode.hdisplay;
> +	/*
> +	 * Allow a framebuffer larger than the panel so a sub-region can be
> +	 * displayed via the plane source rectangle (crop / pan, no scaling).
> +	 */
> +	drm->mode_config.max_width = DRM_SHADOW_PLANE_MAX_WIDTH;

[Severity: Critical]
Can this change cause a heap buffer overflow in mipi_dbi_fb_dirty()?

By allowing the framebuffer to be larger than the panel, userspace can now
use non-zero source offsets. If userspace provides fractional source
coordinates via the atomic ioctl, the damage iterator will round the
coordinates outwards (floor and ceil).

This can result in a merged damage rectangle that is larger than the
physical panel dimensions, which gets passed to
drm_mipi_dbi_plane_helper_atomic_update():

drivers/gpu/drm/drm_mipi_dbi.c:drm_mipi_dbi_plane_helper_atomic_update() {
    ...
    if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &rect))
        mipi_dbi_fb_dirty(&shadow_plane_state->data[0], fb, &rect,
    ...
}

Then in mipi_dbi_fb_dirty(), the inflated rectangle is used to compute the
copy bounds:

drivers/gpu/drm/drm_mipi_dbi.c:mipi_dbi_fb_dirty() {
    ...
    unsigned int height = rect->y2 - rect->y1;
    unsigned int width = rect->x2 - rect->x1;
    ...
    ret = mipi_dbi_buf_copy(tr, src, fb, rect, swap, fmtcnv_state);
    ...
}

Since tx_buf was strictly allocated during drm_mipi_dbi_dev_init() to hold
exactly the panel size, copying based on this inflated width and height will
overflow tx_buf on the heap.

>  	drm->mode_config.min_height = dbidev->mode.vdisplay;
> -	drm->mode_config.max_height = dbidev->mode.vdisplay;
> +	drm->mode_config.max_height = DRM_SHADOW_PLANE_MAX_HEIGHT;
>  	drm->mode_config.funcs = &panel_mipi_dbi_mode_config_funcs;
>  	drm->mode_config.preferred_depth = bpp;
>  	drm->mode_config.helper_private = &panel_mipi_dbi_mode_config_helper_funcs;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260910185030.870-1-frazinjonathan@gmail.com?part=2

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v1 1/2] drm/mipi-dbi: honour the plane source offset when flushing
  2026-09-10 18:48 ` [PATCH v1 1/2] drm/mipi-dbi: honour the plane source offset when flushing Jonathan Frazin
@ 2026-09-10 19:07   ` sashiko-bot
  0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-09-10 19:07 UTC (permalink / raw)
  To: Jonathan Frazin; +Cc: dri-devel

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Partial updates in the sharp-memory driver corrupt the display because framebuffer lines are unconditionally paired with panel line addresses starting at 1. This problem wasn't introduced by this patch, but exists in the current codebase.
--

commit d169c425f8ab54f8c291ce0979baadd0ddecc949
Author: Jonathan Frazin <frazinjonathan@gmail.com>

drm/mipi-dbi: honour the plane source offset when flushing

This commit updates mipi_dbi_fb_dirty() to account for the plane's source
offset. It subtracts src_x and src_y from the damage rectangle when
programming the column and page addresses, ensuring the correct panel window
is addressed for framebuffers larger than the panel.

> diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
> index 25cf04d029f77..38db45a9dbc35 100644
> --- a/drivers/gpu/drm/drm_mipi_dbi.c
> +++ b/drivers/gpu/drm/drm_mipi_dbi.c
[ ... ]
> @@ -298,8 +299,13 @@ static void mipi_dbi_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb,
>  		tr = src->vaddr; /* TODO: Use mapping abstraction properly */
>  	}
>  
> -	mipi_dbi_set_window_address(dbidev, rect->x1, rect->x2 - 1, rect->y1,
> -				    rect->y2 - 1);
> +	/*
> +	 * @rect is in framebuffer coordinates and has been clipped to the plane
> +	 * src rectangle by the damage iterator. The panel is addressed relative
> +	 * to the src origin, so subtract it here.
> +	 */
> +	mipi_dbi_set_window_address(dbidev, rect->x1 - src_x, rect->x2 - 1 - src_x,
> +				    rect->y1 - src_y, rect->y2 - 1 - src_y);

[Severity: High]
This isn't a bug introduced by this patch, but looking at how partial updates
are handled here, I noticed a pre-existing issue in the sharp-memory driver
where partial updates corrupt the display because framebuffer lines are
unconditionally paired with panel line addresses starting at 1.

Looking at drivers/gpu/drm/tiny/sharp-memory.c in
sharp_memory_set_tx_buffer_addresses():

	for (u32 line = 0; line < clip.y2; ++line)
		buffer[line * pitch] = line + 1;

The line addresses unconditionally start at 1 regardless of clip.y1, preparing
the transmit buffer with panel addresses starting at the top.

In drivers/gpu/drm/drm_format_helper.c:drm_fb_xrgb8888_to_mono():

		src32 = memcpy(src32, vaddr, len_src32);
		drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels);
		drm_fb_gray8_to_mono_line(mono, gray8, linepixels);

Data is extracted from the correct y-offset in the source framebuffer but
written sequentially to the start of the destination buffer.

Then in drivers/gpu/drm/tiny/sharp-memory.c:sharp_memory_update_display():

	sharp_memory_set_tx_buffer_addresses(&tx_buffer[1], clip, pitch);
	sharp_memory_set_tx_buffer_data(&tx_buffer[2], fb, vmap, clip, pitch, fmtcnv_state);

	ret = sharp_memory_spi_write(smd->spi, tx_buffer, tx_buffer_size);

The offset data is placed at the start of the transmit buffer and the entire
buffer size is written to the SPI bus, pushing misaligned display data.

When a userspace compositor submits an atomic commit with damage clips where
clip.y1 > 0 (a partial update not starting at the top of the screen), the
damaged region from the framebuffer is extracted but written to the beginning
of the SPI transmit buffer. This causes the updated region to be drawn at the
top of the display rather than its correct coordinates, and unmodified regions
below it are updated with stale or out-of-sync memory.

Since damage clips can be triggered by any unprivileged application indirectly
through standard compositor operations, can this cause severe display
corruption in normal userspace usage?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260910185030.870-1-frazinjonathan@gmail.com?part=1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v1 2/2] drm/tiny: allow a framebuffer larger than the panel on MIPI DBI drivers
  2026-09-10 19:05   ` sashiko-bot
@ 2026-09-11  0:19     ` Jonathan Frazin
  0 siblings, 0 replies; 6+ messages in thread
From: Jonathan Frazin @ 2026-09-11  0:19 UTC (permalink / raw)
  To: sashiko-reviews
  Cc: dri-devel, Thomas Zimmermann, Maxime Ripard, Maarten Lankhorst,
	David Airlie, Simona Vetter, Kamlesh Gurudasani, Alex Lanzano,
	Dave Stevenson, linux-kernel

On Thu, Sep 10, 2026 at 2:05 PM <sashiko-bot@kernel.org> wrote:
> Since tx_buf was strictly allocated during drm_mipi_dbi_dev_init() to hold
> exactly the panel size, copying based on this inflated width and height will
> overflow tx_buf on the heap.

Confirmed. On a fractional plane SRC_X/SRC_Y the damage iterator rounds
the merged rect out by up to a pixel per axis, so it can exceed the
panel and overflow the mode-sized tx_buf. v2 will clamp the rect back to
the panel in mipi_dbi_fb_dirty().

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-09-11  7:50 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-10 18:48 [PATCH v1 0/2] drm/mipi-dbi: display a cropped region of an oversized framebuffer Jonathan Frazin
2026-09-10 18:48 ` [PATCH v1 1/2] drm/mipi-dbi: honour the plane source offset when flushing Jonathan Frazin
2026-09-10 19:07   ` sashiko-bot
2026-09-10 18:48 ` [PATCH v1 2/2] drm/tiny: allow a framebuffer larger than the panel on MIPI DBI drivers Jonathan Frazin
2026-09-10 19:05   ` sashiko-bot
2026-09-11  0:19     ` Jonathan Frazin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox