diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index c64225274807..218cb36757fa 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -28,6 +28,7 @@
  #include <drm/drm_mode_object.h>
  #include <drm/drm_color_mgmt.h>

+struct drm_clip_rect;
  struct drm_crtc;
  struct drm_printer;
  struct drm_modeset_acquire_ctx;
@@ -85,6 +86,9 @@ struct drm_plane_state {
          */
         bool dirty;

+       struct drm_clip_rect *dirty_clips;
+       unsigned int num_dirty_clips;
+
         /**
          * @fence:
          *
diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 8066c508ab50..e00b8247b7c5 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -3521,6 +3521,8 @@ void 
__drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
                 drm_framebuffer_get(state->fb);

         state->dirty = false;
+       state->dirty_clips = NULL;
+       state->num_dirty_clips = 0;
         state->fence = NULL;
         state->commit = NULL;
  }
@@ -3567,6 +3569,8 @@ void 
__drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)

         if (state->commit)
                 drm_crtc_commit_put(state->commit);
+
+       kfree(state->dirty_clips);
  }
  EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);

@@ -3877,8 +3881,20 @@ int drm_atomic_helper_dirtyfb(struct 
drm_framebuffer *fb,
         struct drm_modeset_acquire_ctx ctx;
         struct drm_atomic_state *state;
         struct drm_plane *plane;
+       bool fb_found = false;
         int ret = 0;

+       /* fbdev can flush even when we don't want it to */
+       drm_for_each_plane(plane, fb->dev) {
+               if (plane->state->fb == fb) {
+                       fb_found = true;
+                       break;
+               }
+       }
+
+       if (!fb_found)
+               return 0;
+
         /*
          * When called from ioctl, we are interruptable, but not when
          * called internally (ie. defio worker)
@@ -3907,6 +3923,25 @@ int drm_atomic_helper_dirtyfb(struct 
drm_framebuffer *fb,
                 }

                 plane_state->dirty = true;
+               if (clips && num_clips)
+                       plane_state->dirty_clips = kmemdup(clips, 
num_clips * sizeof(*clips),
+ GFP_KERNEL);
+               else
+                       plane_state->dirty_clips = 
kzalloc(sizeof(*clips), GFP_KERNEL);
+
+               if (!plane_state->dirty_clips) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               if (clips && num_clips) {
+                       plane_state->num_dirty_clips = num_clips;
+               } else {
+                       /* TODO: Maybe choose better max values */
+                       plane_state->dirty_clips->x2 = ~0;
+                       plane_state->dirty_clips->y2 = ~0;
+                       plane_state->num_dirty_clips = 1;
+               }
         }

         ret = drm_atomic_nonblocking_commit(state);
diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c 
b/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c
index e68b528ae64d..1a0c72c496f6 100644
--- a/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c
+++ b/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c
@@ -121,12 +121,14 @@ void tinydrm_display_pipe_update(struct 
drm_simple_display_pipe *pipe,
                                  struct drm_plane_state *old_state)
  {
         struct tinydrm_device *tdev = pipe_to_tinydrm(pipe);
-       struct drm_framebuffer *fb = pipe->plane.state->fb;
+       struct drm_plane_state *new_state = pipe->plane.state;
+       struct drm_framebuffer *fb = new_state->fb;
         struct drm_crtc *crtc = &tdev->pipe.crtc;

-       if (fb && (fb != old_state->fb)) {
+       if (fb && ((fb != old_state->fb) || new_state->dirty_clips)) {
                 if (tdev->fb_dirty)
-                       tdev->fb_dirty(fb, NULL, 0, 0, NULL, 0);
+                       tdev->fb_dirty(fb, NULL, 0, 0, 
new_state->dirty_clips,
+ new_state->num_dirty_clips);
         }

         if (crtc->state->event) {
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c 
b/drivers/gpu/drm/tinydrm/mipi-dbi.c
index 4d1fb31a781f..49dee24dde60 100644
--- a/drivers/gpu/drm/tinydrm/mipi-dbi.c
+++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c
@@ -9,6 +9,7 @@
   * (at your option) any later version.
   */

+#include <drm/drm_atomic_helper.h>
  #include <drm/drm_gem_framebuffer_helper.h>
  #include <drm/tinydrm/mipi-dbi.h>
  #include <drm/tinydrm/tinydrm-helpers.h>
@@ -254,7 +257,7 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb,
  static const struct drm_framebuffer_funcs mipi_dbi_fb_funcs = {
         .destroy        = drm_gem_fb_destroy,
         .create_handle  = drm_gem_fb_create_handle,
-       .dirty          = tinydrm_fb_dirty,
+       .dirty          = drm_atomic_helper_dirtyfb,
  };

  /**
