#include <linux/dma-fence-chain.h>
 #include <linux/dma-resv.h>
+#include <linux/iosys-map.h>
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
+#include <drm/drm_cache.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_panic.h>
 
 #include "gem/i915_gem_object.h"
 #include "i915_scheduler_types.h"
 #include "i915_vma.h"
 #include "i9xx_plane_regs.h"
+#include "intel_bo.h"
 #include "intel_cdclk.h"
 #include "intel_cursor.h"
 #include "intel_display_rps.h"
 #include "intel_display_types.h"
 #include "intel_fb.h"
 #include "intel_fb_pin.h"
+#include "intel_fbdev.h"
 #include "intel_plane.h"
 #include "skl_scaler.h"
 #include "skl_universal_plane.h"
        intel_plane_unpin_fb(old_plane_state);
 }
 
+static void intel_panic_flush(struct drm_plane *plane)
+{
+       struct intel_plane_state *plane_state = to_intel_plane_state(plane->state);
+       struct intel_plane *iplane = to_intel_plane(plane);
+       struct intel_display *display = to_intel_display(iplane);
+       struct drm_framebuffer *fb = plane_state->hw.fb;
+       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+
+       intel_bo_panic_finish(intel_fb);
+
+       /* Flush the cache and don't disable tiling if it's the fbdev framebuffer.*/
+       if (intel_fb == intel_fbdev_framebuffer(display->fbdev.fbdev)) {
+               struct iosys_map map;
+
+               intel_fbdev_get_map(display->fbdev.fbdev, &map);
+               drm_clflush_virt_range(map.vaddr, fb->pitches[0] * fb->height);
+               return;
+       }
+
+       if (fb->modifier && iplane->disable_tiling)
+               iplane->disable_tiling(iplane);
+}
+
+static int intel_get_scanout_buffer(struct drm_plane *plane,
+                                   struct drm_scanout_buffer *sb)
+{
+       struct intel_plane_state *plane_state;
+       struct drm_gem_object *obj;
+       struct drm_framebuffer *fb;
+       struct intel_framebuffer *intel_fb;
+       struct intel_display *display = to_intel_display(plane->dev);
+
+       if (!plane->state || !plane->state->fb || !plane->state->visible)
+               return -ENODEV;
+
+       plane_state = to_intel_plane_state(plane->state);
+       fb = plane_state->hw.fb;
+       intel_fb = to_intel_framebuffer(fb);
+
+       obj = intel_fb_bo(fb);
+       if (!obj)
+               return -ENODEV;
+
+       if (intel_fb == intel_fbdev_framebuffer(display->fbdev.fbdev)) {
+               intel_fbdev_get_map(display->fbdev.fbdev, &sb->map[0]);
+       } else {
+               int ret;
+               /* Can't disable tiling if DPT is in use */
+               if (intel_fb_uses_dpt(fb))
+                       return -EOPNOTSUPP;
+               sb->private = intel_fb;
+               ret = intel_bo_panic_setup(sb);
+               if (ret)
+                       return ret;
+       }
+       sb->width = fb->width;
+       sb->height = fb->height;
+       /* Use the generic linear format, because tiling, RC, CCS, CC
+        * will be disabled in disable_tiling()
+        */
+       sb->format = drm_format_info(fb->format->format);
+       sb->pitch[0] = fb->pitches[0];
+
+       return 0;
+}
+
 static const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
        .prepare_fb = intel_prepare_plane_fb,
        .cleanup_fb = intel_cleanup_plane_fb,
 };
 
+static const struct drm_plane_helper_funcs intel_primary_plane_helper_funcs = {
+       .prepare_fb = intel_prepare_plane_fb,
+       .cleanup_fb = intel_cleanup_plane_fb,
+       .get_scanout_buffer = intel_get_scanout_buffer,
+       .panic_flush = intel_panic_flush,
+};
+
 void intel_plane_helper_add(struct intel_plane *plane)
 {
-       drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
+       if (plane->base.type == DRM_PLANE_TYPE_PRIMARY)
+               drm_plane_helper_add(&plane->base, &intel_primary_plane_helper_funcs);
+       else
+               drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
 }
 
 void intel_plane_init_cursor_vblank_work(struct intel_plane_state *old_plane_state,