Commit b5f636e6 authored by Thomas Zimmermann's avatar Thomas Zimmermann

drm/mipi-dbi: Prepare framebuffer copy operation in pipe-update helpers

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.

v2:
	* keep each driver's existing buffer-mapping patter (Noralf)
	* zero-initialize iosys_map arrays (Noralf)
Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: default avatarNoralf Trønnes <noralf@tronnes.org>
Tested-by: default avatarJavier Martinez Canillas <javierm@redhat.com>
Tested-by: Noralf Trønnes <noralf@tronnes.org> # drm/tiny/mi0283qt
Link: https://patchwork.freedesktop.org/patch/msgid/20221202125644.7917-6-tzimmermann@suse.de
parent 63aa5ec6
...@@ -192,6 +192,7 @@ EXPORT_SYMBOL(mipi_dbi_command_stackbuf); ...@@ -192,6 +192,7 @@ EXPORT_SYMBOL(mipi_dbi_command_stackbuf);
/** /**
* mipi_dbi_buf_copy - Copy a framebuffer, transforming it if necessary * mipi_dbi_buf_copy - Copy a framebuffer, transforming it if necessary
* @dst: The destination buffer * @dst: The destination buffer
* @src: The source buffer
* @fb: The source framebuffer * @fb: The source framebuffer
* @clip: Clipping rectangle of the area to be copied * @clip: Clipping rectangle of the area to be copied
* @swap: When true, swap MSB/LSB of 16-bit values * @swap: When true, swap MSB/LSB of 16-bit values
...@@ -199,12 +200,10 @@ EXPORT_SYMBOL(mipi_dbi_command_stackbuf); ...@@ -199,12 +200,10 @@ EXPORT_SYMBOL(mipi_dbi_command_stackbuf);
* Returns: * Returns:
* Zero on success, negative error code on failure. * 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_rect *clip, bool swap)
{ {
struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); 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 dst_map = IOSYS_MAP_INIT_VADDR(dst); struct iosys_map dst_map = IOSYS_MAP_INIT_VADDR(dst);
int ret; int ret;
...@@ -212,19 +211,15 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, ...@@ -212,19 +211,15 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
if (ret) if (ret)
return 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) { switch (fb->format->format) {
case DRM_FORMAT_RGB565: case DRM_FORMAT_RGB565:
if (swap) if (swap)
drm_fb_swab(&dst_map, NULL, data, fb, clip, !gem->import_attach); drm_fb_swab(&dst_map, NULL, src, fb, clip, !gem->import_attach);
else else
drm_fb_memcpy(&dst_map, NULL, data, fb, clip); drm_fb_memcpy(&dst_map, NULL, src, fb, clip);
break; break;
case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XRGB8888:
drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, data, fb, clip, swap); drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, src, fb, clip, swap);
break; break;
default: default:
drm_err_once(fb->dev, "Format is not supported: %p4cc\n", drm_err_once(fb->dev, "Format is not supported: %p4cc\n",
...@@ -232,8 +227,6 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, ...@@ -232,8 +227,6 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
ret = -EINVAL; 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); drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
return ret; return ret;
...@@ -257,10 +250,9 @@ static void mipi_dbi_set_window_address(struct mipi_dbi_dev *dbidev, ...@@ -257,10 +250,9 @@ static void mipi_dbi_set_window_address(struct mipi_dbi_dev *dbidev,
ys & 0xff, (ye >> 8) & 0xff, ye & 0xff); 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); struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
unsigned int height = rect->y2 - rect->y1; unsigned int height = rect->y2 - rect->y1;
unsigned int width = rect->x2 - rect->x1; unsigned int width = rect->x2 - rect->x1;
...@@ -270,16 +262,9 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) ...@@ -270,16 +262,9 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
bool full; bool full;
void *tr; void *tr;
if (WARN_ON(!fb))
return;
if (!drm_dev_enter(fb->dev, &idx)) if (!drm_dev_enter(fb->dev, &idx))
return; return;
ret = drm_gem_fb_vmap(fb, map, data);
if (ret)
goto err_drm_dev_exit;
full = width == fb->width && height == fb->height; full = width == fb->width && height == fb->height;
DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect));
...@@ -287,11 +272,11 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) ...@@ -287,11 +272,11 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
if (!dbi->dc || !full || swap || if (!dbi->dc || !full || swap ||
fb->format->format == DRM_FORMAT_XRGB8888) { fb->format->format == DRM_FORMAT_XRGB8888) {
tr = dbidev->tx_buf; 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) if (ret)
goto err_msg; goto err_msg;
} else { } 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, mipi_dbi_set_window_address(dbidev, rect->x1, rect->x2 - 1, rect->y1,
...@@ -303,9 +288,6 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) ...@@ -303,9 +288,6 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
if (ret) if (ret)
drm_err_once(fb->dev, "Failed to update display %d\n", 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); drm_dev_exit(idx);
} }
...@@ -338,14 +320,27 @@ EXPORT_SYMBOL(mipi_dbi_pipe_mode_valid); ...@@ -338,14 +320,27 @@ EXPORT_SYMBOL(mipi_dbi_pipe_mode_valid);
void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe, void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *old_state) 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_plane_state *state = pipe->plane.state;
struct drm_framebuffer *fb = state->fb;
struct drm_rect rect; struct drm_rect rect;
int ret;
if (!pipe->crtc.state->active) if (!pipe->crtc.state->active)
return; 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)) 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); EXPORT_SYMBOL(mipi_dbi_pipe_update);
...@@ -373,14 +368,22 @@ void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev, ...@@ -373,14 +368,22 @@ void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev,
.y1 = 0, .y1 = 0,
.y2 = fb->height, .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)) if (!drm_dev_enter(&dbidev->drm, &idx))
return; 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); backlight_enable(dbidev->backlight);
drm_gem_fb_vunmap(fb, map);
err_drm_dev_exit:
drm_dev_exit(idx); drm_dev_exit(idx);
} }
EXPORT_SYMBOL(mipi_dbi_enable_flush); EXPORT_SYMBOL(mipi_dbi_enable_flush);
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <drm/drm_framebuffer.h> #include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h> #include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_managed.h> #include <drm/drm_managed.h>
#include <drm/drm_mipi_dbi.h> #include <drm/drm_mipi_dbi.h>
#include <drm/drm_rect.h> #include <drm/drm_rect.h>
...@@ -76,9 +77,9 @@ static inline int ili9225_command(struct mipi_dbi *dbi, u8 cmd, u16 data) ...@@ -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); 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); struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
unsigned int height = rect->y2 - rect->y1; unsigned int height = rect->y2 - rect->y1;
unsigned int width = rect->x2 - rect->x1; unsigned int width = rect->x2 - rect->x1;
...@@ -100,11 +101,11 @@ static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) ...@@ -100,11 +101,11 @@ static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
if (!dbi->dc || !full || swap || if (!dbi->dc || !full || swap ||
fb->format->format == DRM_FORMAT_XRGB8888) { fb->format->format == DRM_FORMAT_XRGB8888) {
tr = dbidev->tx_buf; 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) if (ret)
goto err_msg; goto err_msg;
} else { } else {
tr = dma_obj->vaddr; tr = src->vaddr; /* TODO: Use mapping abstraction properly */
} }
switch (dbidev->rotation) { switch (dbidev->rotation) {
...@@ -163,13 +164,19 @@ static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe, ...@@ -163,13 +164,19 @@ static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe,
struct drm_plane_state *old_state) struct drm_plane_state *old_state)
{ {
struct drm_plane_state *state = pipe->plane.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; struct drm_rect rect;
if (!pipe->crtc.state->active) if (!pipe->crtc.state->active)
return; 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)) if (drm_atomic_helper_damage_merged(old_state, state, &rect))
ili9225_fb_dirty(state->fb, &rect); ili9225_fb_dirty(&src, fb, &rect);
} }
static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
...@@ -186,6 +193,8 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, ...@@ -186,6 +193,8 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
.y1 = 0, .y1 = 0,
.y2 = fb->height, .y2 = fb->height,
}; };
struct drm_gem_dma_object *dma_obj;
struct iosys_map src;
int ret, idx; int ret, idx;
u8 am_id; u8 am_id;
...@@ -276,7 +285,11 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, ...@@ -276,7 +285,11 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe,
ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x1017); ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x1017);
ili9225_fb_dirty(fb, &rect); dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
iosys_map_set_vaddr(&src, dma_obj->vaddr);
ili9225_fb_dirty(&src, fb, &rect);
out_exit: out_exit:
drm_dev_exit(idx); drm_dev_exit(idx);
} }
......
...@@ -92,25 +92,24 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr, ...@@ -92,25 +92,24 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr,
kfree(buf); 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_rect *clip)
{ {
struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0); int ret;
void *src = dma_obj->vaddr;
int ret = 0;
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
if (ret) if (ret)
return 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); drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
return 0; 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_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
struct mipi_dbi *dbi = &dbidev->dbi; struct mipi_dbi *dbi = &dbidev->dbi;
...@@ -125,7 +124,7 @@ static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) ...@@ -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)); 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) if (ret)
goto err_msg; goto err_msg;
...@@ -154,13 +153,19 @@ static void st7586_pipe_update(struct drm_simple_display_pipe *pipe, ...@@ -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 *old_state)
{ {
struct drm_plane_state *state = pipe->plane.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; struct drm_rect rect;
if (!pipe->crtc.state->active) if (!pipe->crtc.state->active)
return; 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)) 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, 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, ...@@ -176,6 +181,8 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
.y1 = 0, .y1 = 0,
.y2 = fb->height, .y2 = fb->height,
}; };
struct drm_gem_dma_object *dma_obj;
struct iosys_map src;
int idx, ret; int idx, ret;
u8 addr_mode; u8 addr_mode;
...@@ -235,7 +242,10 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, ...@@ -235,7 +242,10 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe,
msleep(100); 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); mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON);
out_exit: out_exit:
......
...@@ -13,9 +13,10 @@ ...@@ -13,9 +13,10 @@
#include <drm/drm_simple_kms_helper.h> #include <drm/drm_simple_kms_helper.h>
struct drm_rect; struct drm_rect;
struct spi_device;
struct gpio_desc; struct gpio_desc;
struct iosys_map;
struct regulator; struct regulator;
struct spi_device;
/** /**
* struct mipi_dbi - MIPI DBI interface * struct mipi_dbi - MIPI DBI interface
...@@ -176,8 +177,9 @@ int mipi_dbi_command_read(struct mipi_dbi *dbi, u8 cmd, u8 *val); ...@@ -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_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, int mipi_dbi_command_stackbuf(struct mipi_dbi *dbi, u8 cmd, const u8 *data,
size_t len); 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); struct drm_rect *clip, bool swap);
/** /**
* mipi_dbi_command - MIPI DCS command with optional parameter(s) * mipi_dbi_command - MIPI DCS command with optional parameter(s)
* @dbi: MIPI DBI structure * @dbi: MIPI DBI structure
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment