* [PATCH 0/4] drm: Add and use drm_fb_dma_get_gem_clipped_addr() helper
@ 2026-09-08 9:07 Chen-Yu Tsai
2026-09-08 9:07 ` [PATCH 1/4] drm/fb-dma-helper: Add drm_fb_dma_get_gem_clipped_addr() Chen-Yu Tsai
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Chen-Yu Tsai @ 2026-09-08 9:07 UTC (permalink / raw)
To: Liu Ying, Laurentiu Palcu, Lucas Stach, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann
Cc: Chen-Yu Tsai, David Airlie, Simona Vetter, linux-sunxi, imx,
dri-devel, linux-arm-kernel, linux-kernel
Hi,
This series adds a helper to retrieve the buffer starting address of a
"clipped" framebuffer. This contrasts with drm_fb_dma_get_gem_addr(),
which gives the address of the full buffer.
Some drivers program their hardware with clipped dimensions, so they
should be using the clipped buffer address as well, unless the hardware
can advance the scanout directly. (Side note: many drivers still use
the non-clipped dimensions.)
The sun4i driver was recently incorrectly converted to use the unclipped
drm_fb_dma_get_gem_addr() helper. This broke offsets into subsampled
pixel groups, but also exposed the mismatch between the dimensions used
vs the buffer address.
Patch 1 adds the new helper to return the buffer address based on
clipped coordinates.
Patch 2 switches the sun4i driver to the new helper, and fixes the
luma plane buffer address offset for subsampled YUV formats.
Patch 3 converts the imx/dc driver to use the new helper. This fixes a
mismatch between the programmed coordinates and the buffer address.
Patch 4 replaces the open coded buffer address calculation in the
imx/dcss driver with the new helper.
Please have a look.
Thanks
ChenYu
Chen-Yu Tsai (4):
drm/fb-dma-helper: Add drm_fb_dma_get_gem_clipped_addr()
drm/sun4i: layers: Fix VI buffer address for clipped offsets
drm/imx/dc: plane: Switch to drm_fb_dma_get_gem_clipped_addr()
drm/imx/dcss: plane: Switch to drm_fb_dma_get_gem_clipped_addr()
drivers/gpu/drm/drm_fb_dma_helper.c | 63 +++++++++++++++++++-------
drivers/gpu/drm/imx/dc/dc-plane.c | 4 +-
drivers/gpu/drm/imx/dcss/dcss-plane.c | 34 ++++++--------
drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 2 +-
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 16 ++++++-
include/drm/drm_fb_dma_helper.h | 4 ++
6 files changed, 83 insertions(+), 40 deletions(-)
--
2.55.0.979.g7e5102b832-goog
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/4] drm/fb-dma-helper: Add drm_fb_dma_get_gem_clipped_addr()
2026-09-08 9:07 [PATCH 0/4] drm: Add and use drm_fb_dma_get_gem_clipped_addr() helper Chen-Yu Tsai
@ 2026-09-08 9:07 ` Chen-Yu Tsai
2026-09-08 9:41 ` Thomas Zimmermann
2026-09-08 9:07 ` [PATCH 2/4] drm/sun4i: layers: Fix VI buffer address for clipped offsets Chen-Yu Tsai
` (2 subsequent siblings)
3 siblings, 1 reply; 6+ messages in thread
From: Chen-Yu Tsai @ 2026-09-08 9:07 UTC (permalink / raw)
To: Liu Ying, Laurentiu Palcu, Lucas Stach, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann
Cc: Chen-Yu Tsai, David Airlie, Simona Vetter, linux-sunxi, imx,
dri-devel, linux-arm-kernel, linux-kernel, stable
drm_fb_dma_get_gem_addr() returns the DMA address to the "unclipped"
framebuffer. However some display drivers want the "clipped" framebuffer
instead, as they are also using the clipped coordinates to program the
hardware.
Some of these drivers are open-coding drm_fb_dma_get_gem_addr() with
the source coordinates replaced, while others have been incorrectly
converted to using drm_fb_dma_get_gem_addr(), which would end up
causing incorrect parts of the framebuffer to be displayed if it were
somehow clipped.
Add drm_fb_dma_get_gem_clipped_addr(), a "clipped" version of
drm_fb_dma_get_gem_addr() for these drivers to use.
Cc: <stable@vger.kernel.org> # dependency for next patch
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/gpu/drm/drm_fb_dma_helper.c | 63 +++++++++++++++++++++--------
include/drm/drm_fb_dma_helper.h | 4 ++
2 files changed, 51 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c
index fd71969d2fb1..a260e7cd5667 100644
--- a/drivers/gpu/drm/drm_fb_dma_helper.c
+++ b/drivers/gpu/drm/drm_fb_dma_helper.c
@@ -59,20 +59,10 @@ struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb,
}
EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_obj);
-/**
- * drm_fb_dma_get_gem_addr() - Get DMA (bus) address for framebuffer, for pixel
- * formats where values are grouped in blocks this will get you the beginning of
- * the block
- * @fb: The framebuffer
- * @state: Which state of drm plane
- * @plane: Which plane
- * Return the DMA GEM address for given framebuffer.
- *
- * This function will usually be called from the PLANE callback functions.
- */
-dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
- struct drm_plane_state *state,
- unsigned int plane)
+static dma_addr_t _drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
+ unsigned int plane,
+ unsigned int x,
+ unsigned int y)
{
struct drm_gem_dma_object *obj;
dma_addr_t dma_addr;
@@ -96,8 +86,8 @@ dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
v_div = fb->format->vsub;
}
- sample_x = (state->src_x >> 16) / h_div;
- sample_y = (state->src_y >> 16) / v_div;
+ sample_x = x / h_div;
+ sample_y = y / v_div;
block_start_y = (sample_y / block_h) * block_h;
num_hblocks = sample_x / block_w;
@@ -106,8 +96,49 @@ dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
return dma_addr;
}
+
+/**
+ * drm_fb_dma_get_gem_addr() - Get DMA (bus) address for unclipped framebuffer,
+ * for pixel formats where values are grouped in blocks this will get you the
+ * beginning of the block
+ * @fb: The framebuffer
+ * @state: Which state of drm plane
+ * @plane: Which plane
+ *
+ * This function will usually be called from the PLANE callback functions.
+ *
+ * Return: GEM DMA address for given framebuffer, unclipped.
+ */
+dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
+ struct drm_plane_state *state,
+ unsigned int plane)
+{
+ return _drm_fb_dma_get_gem_addr(fb, plane, state->src_x >> 16,
+ state->src_y >> 16);
+}
EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_addr);
+/**
+ * drm_fb_dma_get_gem_clipped_addr() - Get DMA (bus) address for clipped
+ * framebuffer, for pixel formats where values are grouped in blocks this
+ * will get you the beginning of the block
+ * @fb: The framebuffer
+ * @state: Which state of drm plane
+ * @plane: Which plane
+ *
+ * This function will usually be called from the PLANE callback functions.
+ *
+ * Return: GEM DMA address for given framebuffer, clipped.
+ */
+dma_addr_t drm_fb_dma_get_gem_clipped_addr(struct drm_framebuffer *fb,
+ struct drm_plane_state *state,
+ unsigned int plane)
+{
+ return _drm_fb_dma_get_gem_addr(fb, plane, state->src.x1 >> 16,
+ state->src.y1 >> 16);
+}
+EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_clipped_addr);
+
/**
* drm_fb_dma_sync_non_coherent - Sync GEM object to non-coherent backing
* memory
diff --git a/include/drm/drm_fb_dma_helper.h b/include/drm/drm_fb_dma_helper.h
index c950732c6d36..b2a0bd7ef9d0 100644
--- a/include/drm/drm_fb_dma_helper.h
+++ b/include/drm/drm_fb_dma_helper.h
@@ -17,6 +17,10 @@ dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
struct drm_plane_state *state,
unsigned int plane);
+dma_addr_t drm_fb_dma_get_gem_clipped_addr(struct drm_framebuffer *fb,
+ struct drm_plane_state *state,
+ unsigned int plane);
+
void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
struct drm_plane_state *old_state,
struct drm_plane_state *state);
--
2.55.0.979.g7e5102b832-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/4] drm/sun4i: layers: Fix VI buffer address for clipped offsets
2026-09-08 9:07 [PATCH 0/4] drm: Add and use drm_fb_dma_get_gem_clipped_addr() helper Chen-Yu Tsai
2026-09-08 9:07 ` [PATCH 1/4] drm/fb-dma-helper: Add drm_fb_dma_get_gem_clipped_addr() Chen-Yu Tsai
@ 2026-09-08 9:07 ` Chen-Yu Tsai
2026-09-08 9:07 ` [PATCH 3/4] drm/imx/dc: plane: Switch to drm_fb_dma_get_gem_clipped_addr() Chen-Yu Tsai
2026-09-08 9:07 ` [PATCH 4/4] drm/imx/dcss: " Chen-Yu Tsai
3 siblings, 0 replies; 6+ messages in thread
From: Chen-Yu Tsai @ 2026-09-08 9:07 UTC (permalink / raw)
To: Liu Ying, Laurentiu Palcu, Lucas Stach, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann
Cc: Chen-Yu Tsai, David Airlie, Simona Vetter, linux-sunxi, imx,
dri-devel, linux-arm-kernel, linux-kernel, stable
Commit 79ac1c945ab8 ("drm/sun4i: layers: Use drm_fb_dma_get_gem_addr() to
get display memory") dropped the code to calculate the framebuffer's DMA
address in favor of drm_fb_dma_get_gem_addr().
This turned out to be wrong in a couple ways. The hardware is programmed
with clipped dimensions, so it needs the buffer address to start at the
clipped boundary. Moving to the helper negated the clipping. Also, when
clipping on the left, the buffer address needs to start at the first
pixel in the sub-sampling group even for the luma plane. The hardware
handles the interpolation internally.
Switch to the new drm_fb_dma_get_gem_clipped_addr(), which provides the
buffer address starting at the clipped boundary. Calculate the intra-group
offset and adjust the luma plane buffer address so that it points to the
start of the sub-sampling group.
Fixes: 79ac1c945ab8 ("drm/sun4i: layers: Use drm_fb_dma_get_gem_addr() to get display memory")
Cc: <stable@vger.kernel.org> # v7.1+, needs drm_fb_dma_get_gem_clipped_addr()
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
This is an alternative to Jernej's original revert:
https://lore.kernel.org/all/3980ea1aeb3f7fe8b4700e36560deeba3d050664.1785772659.git.jernej.skrabec@gmail.com/
---
drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 2 +-
drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 16 +++++++++++++++-
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
index bad102134726..530efae7e13c 100644
--- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c
@@ -130,7 +130,7 @@ static void sun8i_ui_layer_update_buffer(struct sun8i_layer *layer,
ch_base = sun8i_channel_base(layer);
/* Get the start of the displayed memory */
- dma_addr = drm_fb_dma_get_gem_addr(fb, state, 0);
+ dma_addr = drm_fb_dma_get_gem_clipped_addr(fb, state, 0);
/* Set the line width */
DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
index 2e9cda45c04e..7a1d5f1db037 100644
--- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -205,7 +205,21 @@ static void sun8i_vi_layer_update_buffer(struct sun8i_layer *layer,
for (i = 0; i < format->num_planes; i++) {
/* Get the start of the displayed memory */
- dma_addr = drm_fb_dma_get_gem_addr(fb, state, i);
+ dma_addr = drm_fb_dma_get_gem_clipped_addr(fb, state, i);
+
+ /*
+ * The mixer can handle odd offsets into sub-sampled YUV
+ * planes, but needs the address of the first pixel in each
+ * sub-sampled block. Adjust the luma buffer address backwards.
+ */
+ if (i == 0) {
+ u32 x_diff, y_diff;
+
+ x_diff = (state->src.x1 >> 16) & (format->hsub - 1);
+ y_diff = (state->src.y1 >> 16) & (format->vsub - 1);
+ dma_addr -= y_diff * fb->pitches[i];
+ dma_addr -= x_diff * format->cpp[i];
+ }
/* Set the line width */
DRM_DEBUG_DRIVER("Layer %d. line width: %d bytes\n",
--
2.55.0.979.g7e5102b832-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/4] drm/imx/dc: plane: Switch to drm_fb_dma_get_gem_clipped_addr()
2026-09-08 9:07 [PATCH 0/4] drm: Add and use drm_fb_dma_get_gem_clipped_addr() helper Chen-Yu Tsai
2026-09-08 9:07 ` [PATCH 1/4] drm/fb-dma-helper: Add drm_fb_dma_get_gem_clipped_addr() Chen-Yu Tsai
2026-09-08 9:07 ` [PATCH 2/4] drm/sun4i: layers: Fix VI buffer address for clipped offsets Chen-Yu Tsai
@ 2026-09-08 9:07 ` Chen-Yu Tsai
2026-09-08 9:07 ` [PATCH 4/4] drm/imx/dcss: " Chen-Yu Tsai
3 siblings, 0 replies; 6+ messages in thread
From: Chen-Yu Tsai @ 2026-09-08 9:07 UTC (permalink / raw)
To: Liu Ying, Laurentiu Palcu, Lucas Stach, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann
Cc: Chen-Yu Tsai, David Airlie, Simona Vetter, linux-sunxi, imx,
dri-devel, linux-arm-kernel, linux-kernel, stable
The hardware is programmed with clipped source and destination dimensions,
but the framebuffer address is calculated using drm_fb_dma_get_gem_addr(),
which uses the full source dimensions. This will not match the source
offset if the top and/or left sides are clipped.
Switch to the new drm_fb_dma_get_gem_clipped_addr(), which provides the
buffer address starting at the clipped boundary.
Fixes: 711a3b878366 ("drm/imx: Add i.MX8qxp Display Controller KMS")
Cc: <stable@vger.kernel.org> # Needs drm_fb_dma_get_gem_clipped_addr()
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/gpu/drm/imx/dc/dc-plane.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/imx/dc/dc-plane.c b/drivers/gpu/drm/imx/dc/dc-plane.c
index dea7404fe659..7bab75d5dedd 100644
--- a/drivers/gpu/drm/imx/dc/dc-plane.c
+++ b/drivers/gpu/drm/imx/dc/dc-plane.c
@@ -65,7 +65,7 @@ static int dc_plane_check_max_source_resolution(struct drm_plane_state *state)
static int dc_plane_check_fb(struct drm_plane_state *state)
{
struct drm_framebuffer *fb = state->fb;
- dma_addr_t baseaddr = drm_fb_dma_get_gem_addr(fb, state, 0);
+ dma_addr_t baseaddr = drm_fb_dma_get_gem_clipped_addr(fb, state, 0);
/* base address alignment */
if (baseaddr & 0x3) {
@@ -146,7 +146,7 @@ dc_plane_atomic_update(struct drm_plane *plane, struct drm_atomic_commit *state)
src_w = drm_rect_width(&new_state->src) >> 16;
src_h = drm_rect_height(&new_state->src) >> 16;
- baseaddr = drm_fb_dma_get_gem_addr(fb, new_state, 0);
+ baseaddr = drm_fb_dma_get_gem_clipped_addr(fb, new_state, 0);
fu_ops = dc_fu_get_ops(dplane->fu);
--
2.55.0.979.g7e5102b832-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/4] drm/imx/dcss: plane: Switch to drm_fb_dma_get_gem_clipped_addr()
2026-09-08 9:07 [PATCH 0/4] drm: Add and use drm_fb_dma_get_gem_clipped_addr() helper Chen-Yu Tsai
` (2 preceding siblings ...)
2026-09-08 9:07 ` [PATCH 3/4] drm/imx/dc: plane: Switch to drm_fb_dma_get_gem_clipped_addr() Chen-Yu Tsai
@ 2026-09-08 9:07 ` Chen-Yu Tsai
3 siblings, 0 replies; 6+ messages in thread
From: Chen-Yu Tsai @ 2026-09-08 9:07 UTC (permalink / raw)
To: Liu Ying, Laurentiu Palcu, Lucas Stach, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann
Cc: Chen-Yu Tsai, David Airlie, Simona Vetter, linux-sunxi, imx,
dri-devel, linux-arm-kernel, linux-kernel
The i.MX DCSS driver is open coding drm_fb_dma_get_gem_clipped_addr(),
with only a slight difference of rounding down the X offset for the
first plane if the format is packed, sub-sampled YUV. This is likely
to correct the buffer address to the first pixel of the 2-pixel group.
Otherwise the hardware will start the scan-out from the second pixel,
which leads to the U/V components getting swapped around, and the
chroma component of the next pixel group being used.
Switch to drm_fb_dma_get_gem_clipped_addr(), and offset the address by
a pixel if the X offset is odd.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
---
drivers/gpu/drm/imx/dcss/dcss-plane.c | 34 +++++++++++----------------
1 file changed, 14 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/imx/dcss/dcss-plane.c b/drivers/gpu/drm/imx/dcss/dcss-plane.c
index 303e93fd036c..580d9cfb4053 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-plane.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-plane.c
@@ -219,28 +219,22 @@ static void dcss_plane_atomic_set_base(struct dcss_plane *dcss_plane)
struct dcss_dev *dcss = plane->dev->dev_private;
struct drm_framebuffer *fb = state->fb;
const struct drm_format_info *format = fb->format;
- struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
unsigned long p1_ba = 0, p2_ba = 0;
- if (!format->is_yuv ||
- format->format == DRM_FORMAT_NV12 ||
- format->format == DRM_FORMAT_NV21)
- p1_ba = dma_obj->dma_addr + fb->offsets[0] +
- fb->pitches[0] * (state->src.y1 >> 16) +
- format->char_per_block[0] * (state->src.x1 >> 16);
- else if (format->format == DRM_FORMAT_UYVY ||
- format->format == DRM_FORMAT_VYUY ||
- format->format == DRM_FORMAT_YUYV ||
- format->format == DRM_FORMAT_YVYU)
- p1_ba = dma_obj->dma_addr + fb->offsets[0] +
- fb->pitches[0] * (state->src.y1 >> 16) +
- 2 * format->char_per_block[0] * (state->src.x1 >> 17);
-
- if (format->format == DRM_FORMAT_NV12 ||
- format->format == DRM_FORMAT_NV21)
- p2_ba = dma_obj->dma_addr + fb->offsets[1] +
- (((fb->pitches[1] >> 1) * (state->src.y1 >> 17) +
- (state->src.x1 >> 17)) << 1);
+ p1_ba = drm_fb_dma_get_gem_clipped_addr(fb, state, 0);
+
+ /*
+ * TODO fix address until helpers know packed, sub-sampled YUV format block size
+ *
+ * The buffer address for packed, sub-sampled YUV formats such as DRM_FORMAT_UYVY
+ * need to be on the first pixel of each pixel group or block. Otherwise the first
+ * pixel of the next pixel group is read and the U/V values get swapped around.
+ */
+ if (drm_format_info_is_yuv_packed(format))
+ p1_ba -= ((state->src.x1 >> 16) & 1) * format->cpp[0];
+
+ if (format->num_planes > 1)
+ p2_ba = drm_fb_dma_get_gem_clipped_addr(fb, state, 1);
dcss_dpr_addr_set(dcss->dpr, dcss_plane->ch_num, p1_ba, p2_ba,
fb->pitches[0]);
--
2.55.0.979.g7e5102b832-goog
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/4] drm/fb-dma-helper: Add drm_fb_dma_get_gem_clipped_addr()
2026-09-08 9:07 ` [PATCH 1/4] drm/fb-dma-helper: Add drm_fb_dma_get_gem_clipped_addr() Chen-Yu Tsai
@ 2026-09-08 9:41 ` Thomas Zimmermann
0 siblings, 0 replies; 6+ messages in thread
From: Thomas Zimmermann @ 2026-09-08 9:41 UTC (permalink / raw)
To: Chen-Yu Tsai, Liu Ying, Laurentiu Palcu, Lucas Stach,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Maarten Lankhorst,
Maxime Ripard
Cc: David Airlie, Simona Vetter, linux-sunxi, imx, dri-devel,
linux-arm-kernel, linux-kernel, stable
Hi
Am 08.09.26 um 11:07 schrieb Chen-Yu Tsai:
> drm_fb_dma_get_gem_addr() returns the DMA address to the "unclipped"
> framebuffer. However some display drivers want the "clipped" framebuffer
> instead, as they are also using the clipped coordinates to program the
> hardware.
>
> Some of these drivers are open-coding drm_fb_dma_get_gem_addr() with
> the source coordinates replaced, while others have been incorrectly
> converted to using drm_fb_dma_get_gem_addr(), which would end up
> causing incorrect parts of the framebuffer to be displayed if it were
> somehow clipped.
>
> Add drm_fb_dma_get_gem_clipped_addr(), a "clipped" version of
> drm_fb_dma_get_gem_addr() for these drivers to use.
>
> Cc: <stable@vger.kernel.org> # dependency for next patch
> Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
> ---
> drivers/gpu/drm/drm_fb_dma_helper.c | 63 +++++++++++++++++++++--------
> include/drm/drm_fb_dma_helper.h | 4 ++
> 2 files changed, 51 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c
> index fd71969d2fb1..a260e7cd5667 100644
> --- a/drivers/gpu/drm/drm_fb_dma_helper.c
> +++ b/drivers/gpu/drm/drm_fb_dma_helper.c
> @@ -59,20 +59,10 @@ struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb,
> }
> EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_obj);
>
> -/**
> - * drm_fb_dma_get_gem_addr() - Get DMA (bus) address for framebuffer, for pixel
> - * formats where values are grouped in blocks this will get you the beginning of
> - * the block
> - * @fb: The framebuffer
> - * @state: Which state of drm plane
> - * @plane: Which plane
> - * Return the DMA GEM address for given framebuffer.
> - *
> - * This function will usually be called from the PLANE callback functions.
> - */
> -dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
> - struct drm_plane_state *state,
> - unsigned int plane)
> +static dma_addr_t _drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
> + unsigned int plane,
> + unsigned int x,
> + unsigned int y)
> {
> struct drm_gem_dma_object *obj;
> dma_addr_t dma_addr;
> @@ -96,8 +86,8 @@ dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
> v_div = fb->format->vsub;
> }
>
> - sample_x = (state->src_x >> 16) / h_div;
> - sample_y = (state->src_y >> 16) / v_div;
> + sample_x = x / h_div;
> + sample_y = y / v_div;
> block_start_y = (sample_y / block_h) * block_h;
> num_hblocks = sample_x / block_w;
The current code already mixes up responsibilities of the involved
modules. It's a good opportunity to improve that. I think there should
be a block-offset helper for the framebuffer. That function will return
the byte offset of a pixel's block from the beginning of the framebuffer
plane.
/* in drm_framebuffer.{c,h} */
u32 drm_framebuffer_get_block_offset(struct drm_framebuffer *fb, plane,
x, y)
{
/* here goes the current offset calculation from the gem-dma code */
}
In the GEM-DMA code, you can then write your helpers like this
drm_fb_dma_get_gem_addr(...)
{
obj = drm_fb_dma_get_gem_ob(fb)
offset = drm_framebuffer_get_block_offset(obj->base, state->src_x,
state->src_y)
dma_addr = obj->dma_addr + offset;
return dma_addr
}
_get_clipped_gem_addr()
{
/* likewise */
}
This better structures the responsibility. It also works for other GEM
code besides GEM-DMA.
Best regards
Thomas
>
> @@ -106,8 +96,49 @@ dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
>
> return dma_addr;
> }
> +
> +/**
> + * drm_fb_dma_get_gem_addr() - Get DMA (bus) address for unclipped framebuffer,
> + * for pixel formats where values are grouped in blocks this will get you the
> + * beginning of the block
> + * @fb: The framebuffer
> + * @state: Which state of drm plane
> + * @plane: Which plane
> + *
> + * This function will usually be called from the PLANE callback functions.
> + *
> + * Return: GEM DMA address for given framebuffer, unclipped.
> + */
> +dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
> + struct drm_plane_state *state,
> + unsigned int plane)
> +{
> + return _drm_fb_dma_get_gem_addr(fb, plane, state->src_x >> 16,
> + state->src_y >> 16);
> +}
> EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_addr);
>
> +/**
> + * drm_fb_dma_get_gem_clipped_addr() - Get DMA (bus) address for clipped
> + * framebuffer, for pixel formats where values are grouped in blocks this
> + * will get you the beginning of the block
> + * @fb: The framebuffer
> + * @state: Which state of drm plane
> + * @plane: Which plane
> + *
> + * This function will usually be called from the PLANE callback functions.
> + *
> + * Return: GEM DMA address for given framebuffer, clipped.
> + */
> +dma_addr_t drm_fb_dma_get_gem_clipped_addr(struct drm_framebuffer *fb,
> + struct drm_plane_state *state,
> + unsigned int plane)
> +{
> + return _drm_fb_dma_get_gem_addr(fb, plane, state->src.x1 >> 16,
> + state->src.y1 >> 16);
> +}
> +EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_clipped_addr);
> +
> /**
> * drm_fb_dma_sync_non_coherent - Sync GEM object to non-coherent backing
> * memory
> diff --git a/include/drm/drm_fb_dma_helper.h b/include/drm/drm_fb_dma_helper.h
> index c950732c6d36..b2a0bd7ef9d0 100644
> --- a/include/drm/drm_fb_dma_helper.h
> +++ b/include/drm/drm_fb_dma_helper.h
> @@ -17,6 +17,10 @@ dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
> struct drm_plane_state *state,
> unsigned int plane);
>
> +dma_addr_t drm_fb_dma_get_gem_clipped_addr(struct drm_framebuffer *fb,
> + struct drm_plane_state *state,
> + unsigned int plane);
> +
> void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
> struct drm_plane_state *old_state,
> struct drm_plane_state *state);
--
--
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] 6+ messages in thread
end of thread, other threads:[~2026-09-08 9:42 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-08 9:07 [PATCH 0/4] drm: Add and use drm_fb_dma_get_gem_clipped_addr() helper Chen-Yu Tsai
2026-09-08 9:07 ` [PATCH 1/4] drm/fb-dma-helper: Add drm_fb_dma_get_gem_clipped_addr() Chen-Yu Tsai
2026-09-08 9:41 ` Thomas Zimmermann
2026-09-08 9:07 ` [PATCH 2/4] drm/sun4i: layers: Fix VI buffer address for clipped offsets Chen-Yu Tsai
2026-09-08 9:07 ` [PATCH 3/4] drm/imx/dc: plane: Switch to drm_fb_dma_get_gem_clipped_addr() Chen-Yu Tsai
2026-09-08 9:07 ` [PATCH 4/4] drm/imx/dcss: " Chen-Yu Tsai
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox