/**
  * 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
  * 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;
 
        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",
                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;
                         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;
        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));
        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,
        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);
 }
 
 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);
 
                .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);
 
 #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>
        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;
        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) {
                                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,
                .y1 = 0,
                .y2 = fb->height,
        };
+       struct drm_gem_dma_object *dma_obj;
+       struct iosys_map src;
        int ret, idx;
        u8 am_id;
 
 
        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);
 }
 
        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;
 
        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;
 
                               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,
                .y1 = 0,
                .y2 = fb->height,
        };
+       struct drm_gem_dma_object *dma_obj;
+       struct iosys_map src;
        int idx, ret;
        u8 addr_mode;
 
 
        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:
 
 #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
 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