[PATCH RFT v2 1/5] drm: Split framebuffer pixel offset calculation from drm_fb_dma_get_gem_addr()
From: Chen-Yu Tsai <wenst@chromium.org>
Date: 2026-09-16 03:33:44
Also in:
dri-devel, imx, linux-sunxi, lkml, stable
Subsystem:
drm drivers, drm drivers and misc gpu patches, the rest · Maintainers:
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Linus Torvalds
Currently drm_fb_dma_get_gem_addr() calculates the offset into the framebuffer memory for the framebuffer's unclipped source coordinates, adds that to the framebuffer's backing storage, and returns the result. We are about to add a variant that uses the clipped source coordinates, so there is already some reuse of code. However, calculating the data offset for a given pixel is not specific to the DMA FB helpers. The offset is only related to the framebuffer. Split out the offset calculation into a new framebuffer helper so that non-DMA users can also reuse the same code. Suggested-by: Thomas Zimmermann <tzimmermann@suse.de> Cc: <redacted> # dependency for next patch Signed-off-by: Chen-Yu Tsai <wenst@chromium.org> --- Changes since v1: - New patch --- drivers/gpu/drm/drm_fb_dma_helper.c | 28 ++---------------- drivers/gpu/drm/drm_framebuffer.c | 45 +++++++++++++++++++++++++++++ include/drm/drm_framebuffer.h | 3 ++ 3 files changed, 51 insertions(+), 25 deletions(-)
diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c
index fd71969d2fb1..ab0f37d8a5ff 100644
--- a/drivers/gpu/drm/drm_fb_dma_helper.c
+++ b/drivers/gpu/drm/drm_fb_dma_helper.c@@ -75,36 +75,14 @@ dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb, unsigned int plane) { struct drm_gem_dma_object *obj; - dma_addr_t dma_addr; - u8 h_div = 1, v_div = 1; - u32 block_w = drm_format_info_block_width(fb->format, plane); - u32 block_h = drm_format_info_block_height(fb->format, plane); - u32 block_size = fb->format->char_per_block[plane]; - u32 sample_x; - u32 sample_y; - u32 block_start_y; - u32 num_hblocks; obj = drm_fb_dma_get_gem_obj(fb, plane); if (!obj) return 0; - dma_addr = obj->dma_addr + fb->offsets[plane]; - - if (plane > 0) { - h_div = fb->format->hsub; - v_div = fb->format->vsub; - } - - sample_x = (state->src_x >> 16) / h_div; - sample_y = (state->src_y >> 16) / v_div; - block_start_y = (sample_y / block_h) * block_h; - num_hblocks = sample_x / block_w; - - dma_addr += fb->pitches[plane] * block_start_y; - dma_addr += block_size * num_hblocks; - - return dma_addr; + return obj->dma_addr + drm_framebuffer_get_block_offset(fb, plane, + state->src_x >> 16, + state->src_y >> 16); } EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_addr);
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index d32aceb6ca9b..9e1231162047 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c@@ -1208,6 +1208,51 @@ void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent, } } +/** + * drm_framebuffer_get_block_offset() - Get offset to start of pixel block for + * the given framebuffer and coordinates. + * @fb: The framebuffer + * @plane: Which plane + * @x: x coordinate for pixel + * @y: y coordinate for pixel + * + * This function will usually be called from the PLANE callback functions, + * or from one of the helpers that calculates the framebuffer's DMA address. + * + * Return: offset from start of framebuffer to start of pixel block + */ +u32 drm_framebuffer_get_block_offset(struct drm_framebuffer *fb, unsigned int plane, + unsigned int x, unsigned int y) +{ + u8 h_div = 1, v_div = 1; + u32 block_w = drm_format_info_block_width(fb->format, plane); + u32 block_h = drm_format_info_block_height(fb->format, plane); + u32 block_size = fb->format->char_per_block[plane]; + u32 sample_x; + u32 sample_y; + u32 block_start_y; + u32 num_hblocks; + u32 offset; + + offset = fb->offsets[plane]; + + if (plane > 0) { + h_div = fb->format->hsub; + v_div = fb->format->vsub; + } + + 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; + + offset += fb->pitches[plane] * block_start_y; + offset += block_size * num_hblocks; + + return offset; +} +EXPORT_SYMBOL(drm_framebuffer_get_block_offset); + #ifdef CONFIG_DEBUG_FS static int drm_framebuffer_info(struct seq_file *m, void *data) {
diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
index 38b24fc8978d..c07aea1cc59f 100644
--- a/include/drm/drm_framebuffer.h
+++ b/include/drm/drm_framebuffer.h@@ -220,6 +220,9 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb); void drm_framebuffer_cleanup(struct drm_framebuffer *fb); void drm_framebuffer_unregister_private(struct drm_framebuffer *fb); +u32 drm_framebuffer_get_block_offset(struct drm_framebuffer *fb, unsigned int plane, + unsigned int x, unsigned int y); + /** * drm_framebuffer_get - acquire a framebuffer reference * @fb: DRM framebuffer
--
2.55.0.1032.g73a4cd73de-goog