}
 
+static void ast_wait_for_vretrace(struct ast_private *ast)
+{
+       unsigned long timeout = jiffies + HZ;
+       u8 vgair1;
+
+       do {
+               vgair1 = ast_io_read8(ast, AST_IO_INPUT_STATUS1_READ);
+       } while (!(vgair1 & AST_IO_VGAIR1_VREFRESH) && time_before(jiffies, timeout));
+}
+
 /*
  * Primary plane
  */
 ast_crtc_helper_atomic_disable(struct drm_crtc *crtc,
                               struct drm_crtc_state *old_crtc_state)
 {
+       struct drm_device *dev = crtc->dev;
+       struct ast_private *ast = to_ast_private(dev);
+
        ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+
+       /*
+        * HW cursors require the underlying primary plane and CRTC to
+        * display a valid mode and image. This is not the case during
+        * full modeset operations. So we temporarily disable any active
+        * plane, including the HW cursor. Each plane's atomic_update()
+        * helper will re-enable it if necessary.
+        *
+        * We only do this during *full* modesets. It does not affect
+        * simple pageflips on the planes.
+        */
+       drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false);
+
+       /*
+        * Ensure that no scanout takes place before reprogramming mode
+        * and format registers.
+        */
+       ast_wait_for_vretrace(ast);
 }
 
 static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {