From: Thomas Zimmermann Date: Fri, 2 Dec 2022 12:56:41 +0000 (+0100) Subject: drm/mipi-dbi: Prepare framebuffer copy operation in pipe-update helpers X-Git-Tag: v6.6.7~1918^2~23^2~1212 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b5f636e63b807fdeba5d61260e5f6b24f6834f69;p=platform%2Fkernel%2Flinux-starfive.git 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: Thomas Zimmermann Reviewed-by: Noralf Trønnes Tested-by: Javier Martinez Canillas Tested-by: Noralf Trønnes # drm/tiny/mi0283qt Link: https://patchwork.freedesktop.org/patch/msgid/20221202125644.7917-6-tzimmermann@suse.de --- diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index a6ac565..f581233 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,10 @@ 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 dst_map = IOSYS_MAP_INIT_VADDR(dst); int ret; @@ -212,19 +211,15 @@ 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) - 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 - drm_fb_memcpy(&dst_map, NULL, data, fb, clip); + drm_fb_memcpy(&dst_map, NULL, src, fb, clip); break; 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; default: 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, 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 +250,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 +262,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 +272,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 +288,6 @@ err_msg: 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 +320,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 +368,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 f05a2d2..ae94c74 100644 --- a/drivers/gpu/drm/tiny/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -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) { @@ -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 *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)) - ili9225_fb_dirty(state->fb, &rect); + ili9225_fb_dirty(&src, fb, &rect); } 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, .y2 = fb->height, }; + struct drm_gem_dma_object *dma_obj; + struct iosys_map src; int ret, idx; u8 am_id; @@ -276,7 +285,11 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, 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: drm_dev_exit(idx); } diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index 6bdd23e..e773b1f 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 8c4ea79..36ac849 100644 --- a/include/drm/drm_mipi_dbi.h +++ b/include/drm/drm_mipi_dbi.h @@ -13,9 +13,10 @@ #include 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