[PATCH 5/8] drm/mipi-dbi: Prepare framebuffer copy operation in pipe-update helpers
Thomas Zimmermann
tzimmermann at suse.de
Mon Nov 21 10:45:29 UTC 2022
Move the vmap/vunmap blocks from the inner fb_dirty helpers into the
MIPI DBI update helpers. The function calls can result in waiting and/or
processing overhead. Reduce the penalties by executing the functions once
in the outer-most function of the pipe update.
This change also prepares for MIPI DBI for shadow-plane helpers. With
shadow-plane helpers, transfer source buffers are mapped into kernel
address space automatically.
Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de>
---
drivers/gpu/drm/drm_mipi_dbi.c | 60 +++++++++++++++++++---------------
drivers/gpu/drm/tiny/ili9225.c | 31 ++++++++++++++----
drivers/gpu/drm/tiny/st7586.c | 28 +++++++++++-----
include/drm/drm_mipi_dbi.h | 6 ++--
4 files changed, 81 insertions(+), 44 deletions(-)
diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index a6ac565808765..40e59a3a6481e 100644
--- a/drivers/gpu/drm/drm_mipi_dbi.c
+++ b/drivers/gpu/drm/drm_mipi_dbi.c
@@ -192,6 +192,7 @@ EXPORT_SYMBOL(mipi_dbi_command_stackbuf);
/**
* mipi_dbi_buf_copy - Copy a framebuffer, transforming it if necessary
* @dst: The destination buffer
+ * @src: The source buffer
* @fb: The source framebuffer
* @clip: Clipping rectangle of the area to be copied
* @swap: When true, swap MSB/LSB of 16-bit values
@@ -199,12 +200,13 @@ EXPORT_SYMBOL(mipi_dbi_command_stackbuf);
* Returns:
* Zero on success, negative error code on failure.
*/
-int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
+int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer *fb,
struct drm_rect *clip, bool swap)
{
struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
- struct iosys_map map[DRM_FORMAT_MAX_PLANES];
- struct iosys_map data[DRM_FORMAT_MAX_PLANES];
+ struct iosys_map data[DRM_FORMAT_MAX_PLANES] = {
+ *src,
+ };
struct iosys_map dst_map = IOSYS_MAP_INIT_VADDR(dst);
int ret;
@@ -212,10 +214,6 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
if (ret)
return ret;
- ret = drm_gem_fb_vmap(fb, map, data);
- if (ret)
- goto out_drm_gem_fb_end_cpu_access;
-
switch (fb->format->format) {
case DRM_FORMAT_RGB565:
if (swap)
@@ -232,8 +230,6 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
ret = -EINVAL;
}
- drm_gem_fb_vunmap(fb, map);
-out_drm_gem_fb_end_cpu_access:
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
return ret;
@@ -257,10 +253,9 @@ static void mipi_dbi_set_window_address(struct mipi_dbi_dev *dbidev,
ys & 0xff, (ye >> 8) & 0xff, ye & 0xff);
}
-static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
+static void mipi_dbi_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb,
+ struct drm_rect *rect)
{
- struct iosys_map map[DRM_FORMAT_MAX_PLANES];
- struct iosys_map data[DRM_FORMAT_MAX_PLANES];
struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
unsigned int height = rect->y2 - rect->y1;
unsigned int width = rect->x2 - rect->x1;
@@ -270,16 +265,9 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
bool full;
void *tr;
- if (WARN_ON(!fb))
- return;
-
if (!drm_dev_enter(fb->dev, &idx))
return;
- ret = drm_gem_fb_vmap(fb, map, data);
- if (ret)
- goto err_drm_dev_exit;
-
full = width == fb->width && height == fb->height;
DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
@@ -287,11 +275,11 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
if (!dbi->dc || !full || swap ||
fb->format->format == DRM_FORMAT_XRGB8888) {
tr = dbidev->tx_buf;
- ret = mipi_dbi_buf_copy(dbidev->tx_buf, fb, rect, swap);
+ ret = mipi_dbi_buf_copy(tr, src, fb, rect, swap);
if (ret)
goto err_msg;
} else {
- tr = data[0].vaddr; /* TODO: Use mapping abstraction properly */
+ tr = src->vaddr; /* TODO: Use mapping abstraction properly */
}
mipi_dbi_set_window_address(dbidev, rect->x1, rect->x2 - 1, rect->y1,
@@ -303,9 +291,6 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
if (ret)
drm_err_once(fb->dev, "Failed to update display %d\n", ret);
- drm_gem_fb_vunmap(fb, map);
-
-err_drm_dev_exit:
drm_dev_exit(idx);
}
@@ -338,14 +323,27 @@ EXPORT_SYMBOL(mipi_dbi_pipe_mode_valid);
void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *old_state)
{
+ struct iosys_map map[DRM_FORMAT_MAX_PLANES];
+ struct iosys_map data[DRM_FORMAT_MAX_PLANES];
struct drm_plane_state *state = pipe->plane.state;
+ struct drm_framebuffer *fb = state->fb;
struct drm_rect rect;
+ int ret;
if (!pipe->crtc.state->active)
return;
+ if (WARN_ON(!fb))
+ return;
+
+ ret = drm_gem_fb_vmap(fb, map, data);
+ if (ret)
+ return;
+
if (drm_atomic_helper_damage_merged(old_state, state, &rect))
- mipi_dbi_fb_dirty(state->fb, &rect);
+ mipi_dbi_fb_dirty(&data[0], fb, &rect);
+
+ drm_gem_fb_vunmap(fb, map);
}
EXPORT_SYMBOL(mipi_dbi_pipe_update);
@@ -373,14 +371,22 @@ void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev,
.y1 = 0,
.y2 = fb->height,
};
- int idx;
+ struct iosys_map map[DRM_FORMAT_MAX_PLANES];
+ struct iosys_map data[DRM_FORMAT_MAX_PLANES];
+ int idx, ret;
if (!drm_dev_enter(&dbidev->drm, &idx))
return;
- mipi_dbi_fb_dirty(fb, &rect);
+ ret = drm_gem_fb_vmap(fb, map, data);
+ if (ret)
+ goto err_drm_dev_exit;
+
+ mipi_dbi_fb_dirty(&data[0], fb, &rect);
backlight_enable(dbidev->backlight);
+ drm_gem_fb_vunmap(fb, map);
+err_drm_dev_exit:
drm_dev_exit(idx);
}
EXPORT_SYMBOL(mipi_dbi_enable_flush);
diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c
index f05a2d25866c1..0115c4090f9e7 100644
--- a/drivers/gpu/drm/tiny/ili9225.c
+++ b/drivers/gpu/drm/tiny/ili9225.c
@@ -25,6 +25,7 @@
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_mipi_dbi.h>
#include <drm/drm_rect.h>
@@ -76,9 +77,9 @@ static inline int ili9225_command(struct mipi_dbi *dbi, u8 cmd, u16 data)
return mipi_dbi_command_buf(dbi, cmd, par, 2);
}
-static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
+static void ili9225_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb,
+ struct drm_rect *rect)
{
- struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
unsigned int height = rect->y2 - rect->y1;
unsigned int width = rect->x2 - rect->x1;
@@ -100,11 +101,11 @@ static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
if (!dbi->dc || !full || swap ||
fb->format->format == DRM_FORMAT_XRGB8888) {
tr = dbidev->tx_buf;
- ret = mipi_dbi_buf_copy(dbidev->tx_buf, fb, rect, swap);
+ ret = mipi_dbi_buf_copy(tr, src, fb, rect, swap);
if (ret)
goto err_msg;
} else {
- tr = dma_obj->vaddr;
+ tr = src->vaddr; /* TODO: Use mapping abstraction properly */
}
switch (dbidev->rotation) {
@@ -162,14 +163,24 @@ static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *old_state)
{
+ struct iosys_map map[DRM_FORMAT_MAX_PLANES];
+ struct iosys_map data[DRM_FORMAT_MAX_PLANES];
struct drm_plane_state *state = pipe->plane.state;
+ struct drm_framebuffer *fb = state->fb;
struct drm_rect rect;
+ int ret;
if (!pipe->crtc.state->active)
return;
+ ret = drm_gem_fb_vmap(fb, map, data);
+ if (ret)
+ return;
+
if (drm_atomic_helper_damage_merged(old_state, state, &rect))
- ili9225_fb_dirty(state->fb, &rect);
+ ili9225_fb_dirty(&data[0], fb, &rect);
+
+ drm_gem_fb_vunmap(fb, map);
}
static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
@@ -186,6 +197,8 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
.y1 = 0,
.y2 = fb->height,
};
+ struct iosys_map map[DRM_FORMAT_MAX_PLANES];
+ struct iosys_map data[DRM_FORMAT_MAX_PLANES];
int ret, idx;
u8 am_id;
@@ -276,7 +289,13 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x1017);
- ili9225_fb_dirty(fb, &rect);
+ ret = drm_gem_fb_vmap(fb, map, data);
+ if (ret)
+ goto out_exit;
+
+ ili9225_fb_dirty(&data[0], fb, &rect);
+
+ drm_gem_fb_vunmap(fb, map);
out_exit:
drm_dev_exit(idx);
}
diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c
index 6bdd23e2a47c7..e773b1f2fd5f3 100644
--- a/drivers/gpu/drm/tiny/st7586.c
+++ b/drivers/gpu/drm/tiny/st7586.c
@@ -92,25 +92,24 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr,
kfree(buf);
}
-static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb,
+static int st7586_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer *fb,
struct drm_rect *clip)
{
- struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
- void *src = dma_obj->vaddr;
- int ret = 0;
+ int ret;
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
if (ret)
return ret;
- st7586_xrgb8888_to_gray332(dst, src, fb, clip);
+ st7586_xrgb8888_to_gray332(dst, src->vaddr, fb, clip);
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
return 0;
}
-static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
+static void st7586_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb,
+ struct drm_rect *rect)
{
struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
struct mipi_dbi *dbi = &dbidev->dbi;
@@ -125,7 +124,7 @@ static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
- ret = st7586_buf_copy(dbidev->tx_buf, fb, rect);
+ ret = st7586_buf_copy(dbidev->tx_buf, src, fb, rect);
if (ret)
goto err_msg;
@@ -154,13 +153,19 @@ static void st7586_pipe_update(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *old_state)
{
struct drm_plane_state *state = pipe->plane.state;
+ struct drm_framebuffer *fb = state->fb;
+ struct drm_gem_dma_object *dma_obj;
+ struct iosys_map src;
struct drm_rect rect;
if (!pipe->crtc.state->active)
return;
+ dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
+ iosys_map_set_vaddr(&src, dma_obj->vaddr);
+
if (drm_atomic_helper_damage_merged(old_state, state, &rect))
- st7586_fb_dirty(state->fb, &rect);
+ st7586_fb_dirty(&src, fb, &rect);
}
static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
@@ -176,6 +181,8 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
.y1 = 0,
.y2 = fb->height,
};
+ struct drm_gem_dma_object *dma_obj;
+ struct iosys_map src;
int idx, ret;
u8 addr_mode;
@@ -235,7 +242,10 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
msleep(100);
- st7586_fb_dirty(fb, &rect);
+ dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
+ iosys_map_set_vaddr(&src, dma_obj->vaddr);
+
+ st7586_fb_dirty(&src, fb, &rect);
mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
out_exit:
diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h
index 8c4ea7956d61d..36ac8495566b0 100644
--- a/include/drm/drm_mipi_dbi.h
+++ b/include/drm/drm_mipi_dbi.h
@@ -13,9 +13,10 @@
#include <drm/drm_simple_kms_helper.h>
struct drm_rect;
-struct spi_device;
struct gpio_desc;
+struct iosys_map;
struct regulator;
+struct spi_device;
/**
* struct mipi_dbi - MIPI DBI interface
@@ -176,8 +177,9 @@ int mipi_dbi_command_read(struct mipi_dbi *dbi, u8 cmd, u8 *val);
int mipi_dbi_command_buf(struct mipi_dbi *dbi, u8 cmd, u8 *data, size_t len);
int mipi_dbi_command_stackbuf(struct mipi_dbi *dbi, u8 cmd, const u8 *data,
size_t len);
-int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
+int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer *fb,
struct drm_rect *clip, bool swap);
+
/**
* mipi_dbi_command - MIPI DCS command with optional parameter(s)
* @dbi: MIPI DBI structure
--
2.38.1
More information about the dri-devel
mailing list