return DIV_ROUND_UP(pixel_rate * num, den);
 }
 
-static void i9xx_update_plane(struct intel_plane *plane,
-                             const struct intel_crtc_state *crtc_state,
-                             const struct intel_plane_state *plane_state)
+/* TODO: split into noarm+arm pair */
+static void i9xx_plane_update_arm(struct intel_plane *plane,
+                                 const struct intel_crtc_state *crtc_state,
+                                 const struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
-static void i9xx_disable_plane(struct intel_plane *plane,
-                              const struct intel_crtc_state *crtc_state)
+static void i9xx_plane_disable_arm(struct intel_plane *plane,
+                                  const struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
                        plane->max_stride = ilk_primary_max_stride;
        }
 
-       plane->update_plane = i9xx_update_plane;
-       plane->disable_plane = i9xx_disable_plane;
+       plane->update_arm = i9xx_plane_update_arm;
+       plane->disable_arm = i9xx_plane_disable_arm;
        plane->get_hw_state = i9xx_plane_get_hw_state;
        plane->check_plane = i9xx_plane_check;
 
 
        return NULL;
 }
 
-void intel_update_plane(struct intel_plane *plane,
-                       const struct intel_crtc_state *crtc_state,
-                       const struct intel_plane_state *plane_state)
+void intel_plane_update_noarm(struct intel_plane *plane,
+                             const struct intel_crtc_state *crtc_state,
+                             const struct intel_plane_state *plane_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 
-       trace_intel_update_plane(&plane->base, crtc);
+       trace_intel_plane_update_noarm(&plane->base, crtc);
+
+       if (plane->update_noarm)
+               plane->update_noarm(plane, crtc_state, plane_state);
+}
+
+void intel_plane_update_arm(struct intel_plane *plane,
+                           const struct intel_crtc_state *crtc_state,
+                           const struct intel_plane_state *plane_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+       trace_intel_plane_update_arm(&plane->base, crtc);
 
        if (crtc_state->uapi.async_flip && plane->async_flip)
                plane->async_flip(plane, crtc_state, plane_state, true);
        else
-               plane->update_plane(plane, crtc_state, plane_state);
+               plane->update_arm(plane, crtc_state, plane_state);
 }
 
-void intel_disable_plane(struct intel_plane *plane,
-                        const struct intel_crtc_state *crtc_state)
+void intel_plane_disable_arm(struct intel_plane *plane,
+                            const struct intel_crtc_state *crtc_state)
 {
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 
-       trace_intel_disable_plane(&plane->base, crtc);
-       plane->disable_plane(plane, crtc_state);
+       trace_intel_plane_disable_arm(&plane->base, crtc);
+       plane->disable_arm(plane, crtc_state);
 }
 
-void skl_update_planes_on_crtc(struct intel_atomic_state *state,
-                              struct intel_crtc *crtc)
+void intel_update_planes_on_crtc(struct intel_atomic_state *state,
+                                struct intel_crtc *crtc)
+{
+       struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(state, crtc);
+       u32 update_mask = new_crtc_state->update_planes;
+       struct intel_plane_state *new_plane_state;
+       struct intel_plane *plane;
+       int i;
+
+       if (new_crtc_state->uapi.async_flip)
+               return;
+
+       /*
+        * Since we only write non-arming registers here,
+        * the order does not matter even for skl+.
+        */
+       for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) {
+               if (crtc->pipe != plane->pipe ||
+                   !(update_mask & BIT(plane->id)))
+                       continue;
+
+               /* TODO: for mailbox updates this should be skipped */
+               if (new_plane_state->uapi.visible ||
+                   new_plane_state->planar_slave)
+                       intel_plane_update_noarm(plane, new_crtc_state, new_plane_state);
+       }
+}
+
+void skl_arm_planes_on_crtc(struct intel_atomic_state *state,
+                           struct intel_crtc *crtc)
 {
        struct intel_crtc_state *old_crtc_state =
                intel_atomic_get_old_crtc_state(state, crtc);
                struct intel_plane_state *new_plane_state =
                        intel_atomic_get_new_plane_state(state, plane);
 
+               /*
+                * TODO: for mailbox updates intel_plane_update_noarm()
+                * would have to be called here as well.
+                */
                if (new_plane_state->uapi.visible ||
-                   new_plane_state->planar_slave) {
-                       intel_update_plane(plane, new_crtc_state, new_plane_state);
-               } else {
-                       intel_disable_plane(plane, new_crtc_state);
-               }
+                   new_plane_state->planar_slave)
+                       intel_plane_update_arm(plane, new_crtc_state, new_plane_state);
+               else
+                       intel_plane_disable_arm(plane, new_crtc_state);
        }
 }
 
-void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
-                               struct intel_crtc *crtc)
+void i9xx_arm_planes_on_crtc(struct intel_atomic_state *state,
+                            struct intel_crtc *crtc)
 {
        struct intel_crtc_state *new_crtc_state =
                intel_atomic_get_new_crtc_state(state, crtc);
                    !(update_mask & BIT(plane->id)))
                        continue;
 
+               /*
+                * TODO: for mailbox updates intel_plane_update_noarm()
+                * would have to be called here as well.
+                */
                if (new_plane_state->uapi.visible)
-                       intel_update_plane(plane, new_crtc_state, new_plane_state);
+                       intel_plane_update_arm(plane, new_crtc_state, new_plane_state);
                else
-                       intel_disable_plane(plane, new_crtc_state);
+                       intel_plane_disable_arm(plane, new_crtc_state);
        }
 }
 
 
                                       struct intel_crtc *crtc);
 void intel_plane_copy_hw_state(struct intel_plane_state *plane_state,
                               const struct intel_plane_state *from_plane_state);
-void intel_update_plane(struct intel_plane *plane,
-                       const struct intel_crtc_state *crtc_state,
-                       const struct intel_plane_state *plane_state);
-void intel_disable_plane(struct intel_plane *plane,
-                        const struct intel_crtc_state *crtc_state);
+void intel_plane_update_noarm(struct intel_plane *plane,
+                             const struct intel_crtc_state *crtc_state,
+                             const struct intel_plane_state *plane_state);
+void intel_plane_update_arm(struct intel_plane *plane,
+                           const struct intel_crtc_state *crtc_state,
+                           const struct intel_plane_state *plane_state);
+void intel_plane_disable_arm(struct intel_plane *plane,
+                            const struct intel_crtc_state *crtc_state);
 struct intel_plane *intel_plane_alloc(void);
 void intel_plane_free(struct intel_plane *plane);
 struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane);
 void intel_plane_destroy_state(struct drm_plane *plane,
                               struct drm_plane_state *state);
-void skl_update_planes_on_crtc(struct intel_atomic_state *state,
-                              struct intel_crtc *crtc);
-void i9xx_update_planes_on_crtc(struct intel_atomic_state *state,
-                               struct intel_crtc *crtc);
+void intel_update_planes_on_crtc(struct intel_atomic_state *state,
+                                struct intel_crtc *crtc);
+void skl_arm_planes_on_crtc(struct intel_atomic_state *state,
+                           struct intel_crtc *crtc);
+void i9xx_arm_planes_on_crtc(struct intel_atomic_state *state,
+                            struct intel_crtc *crtc);
 int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
                                        struct intel_crtc_state *crtc_state,
                                        const struct intel_plane_state *old_plane_state,
 
        return 0;
 }
 
-static void i845_update_cursor(struct intel_plane *plane,
-                              const struct intel_crtc_state *crtc_state,
-                              const struct intel_plane_state *plane_state)
+/* TODO: split into noarm+arm pair */
+static void i845_cursor_update_arm(struct intel_plane *plane,
+                                  const struct intel_crtc_state *crtc_state,
+                                  const struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        u32 cntl = 0, base = 0, pos = 0, size = 0;
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
-static void i845_disable_cursor(struct intel_plane *plane,
-                               const struct intel_crtc_state *crtc_state)
+static void i845_cursor_disable_arm(struct intel_plane *plane,
+                                   const struct intel_crtc_state *crtc_state)
 {
-       i845_update_cursor(plane, crtc_state, NULL);
+       i845_cursor_update_arm(plane, crtc_state, NULL);
 }
 
 static bool i845_cursor_get_hw_state(struct intel_plane *plane,
        return 0;
 }
 
-static void i9xx_update_cursor(struct intel_plane *plane,
-                              const struct intel_crtc_state *crtc_state,
-                              const struct intel_plane_state *plane_state)
+/* TODO: split into noarm+arm pair */
+static void i9xx_cursor_update_arm(struct intel_plane *plane,
+                                  const struct intel_crtc_state *crtc_state,
+                                  const struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum pipe pipe = plane->pipe;
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
-static void i9xx_disable_cursor(struct intel_plane *plane,
-                               const struct intel_crtc_state *crtc_state)
+static void i9xx_cursor_disable_arm(struct intel_plane *plane,
+                                   const struct intel_crtc_state *crtc_state)
 {
-       i9xx_update_cursor(plane, crtc_state, NULL);
+       i9xx_cursor_update_arm(plane, crtc_state, NULL);
 }
 
 static bool i9xx_cursor_get_hw_state(struct intel_plane *plane,
         */
        crtc_state->active_planes = new_crtc_state->active_planes;
 
-       if (new_plane_state->uapi.visible)
-               intel_update_plane(plane, crtc_state, new_plane_state);
-       else
-               intel_disable_plane(plane, crtc_state);
+       if (new_plane_state->uapi.visible) {
+               intel_plane_update_noarm(plane, crtc_state, new_plane_state);
+               intel_plane_update_arm(plane, crtc_state, new_plane_state);
+       } else {
+               intel_plane_disable_arm(plane, crtc_state);
+       }
 
        intel_plane_unpin_fb(old_plane_state);
 
 
        if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
                cursor->max_stride = i845_cursor_max_stride;
-               cursor->update_plane = i845_update_cursor;
-               cursor->disable_plane = i845_disable_cursor;
+               cursor->update_arm = i845_cursor_update_arm;
+               cursor->disable_arm = i845_cursor_disable_arm;
                cursor->get_hw_state = i845_cursor_get_hw_state;
                cursor->check_plane = i845_check_cursor;
        } else {
                cursor->max_stride = i9xx_cursor_max_stride;
-               cursor->update_plane = i9xx_update_cursor;
-               cursor->disable_plane = i9xx_disable_cursor;
+               cursor->update_arm = i9xx_cursor_update_arm;
+               cursor->disable_arm = i9xx_cursor_disable_arm;
                cursor->get_hw_state = i9xx_cursor_get_hw_state;
                cursor->check_plane = i9xx_check_cursor;
        }
 
        if (DISPLAY_VER(dev_priv) == 2 && !crtc_state->active_planes)
                intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false);
 
-       intel_disable_plane(plane, crtc_state);
+       intel_plane_disable_arm(plane, crtc_state);
        intel_wait_for_vblank(dev_priv, crtc->pipe);
 }
 
                    !(update_mask & BIT(plane->id)))
                        continue;
 
-               intel_disable_plane(plane, new_crtc_state);
+               intel_plane_disable_arm(plane, new_crtc_state);
 
                if (old_plane_state->uapi.visible)
                        fb_bits |= plane->frontbuffer_bit;
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
        struct intel_plane *plane = to_intel_plane(crtc->base.primary);
 
-       plane->disable_plane(plane, crtc_state);
+       plane->disable_arm(plane, crtc_state);
 }
 
 static void ilk_crtc_enable(struct intel_atomic_state *state,
 
        intel_fbc_update(state, crtc);
 
+       intel_update_planes_on_crtc(state, crtc);
+
        /* Perform vblank evasion around commit operation */
        intel_pipe_update_start(new_crtc_state);
 
        commit_pipe_pre_planes(state, crtc);
 
        if (DISPLAY_VER(dev_priv) >= 9)
-               skl_update_planes_on_crtc(state, crtc);
+               skl_arm_planes_on_crtc(state, crtc);
        else
-               i9xx_update_planes_on_crtc(state, crtc);
+               i9xx_arm_planes_on_crtc(state, crtc);
 
        commit_pipe_post_planes(state, crtc);
 
 
        unsigned int (*max_stride)(struct intel_plane *plane,
                                   u32 pixel_format, u64 modifier,
                                   unsigned int rotation);
-       void (*update_plane)(struct intel_plane *plane,
+       /* Write all non-self arming plane registers */
+       void (*update_noarm)(struct intel_plane *plane,
                             const struct intel_crtc_state *crtc_state,
                             const struct intel_plane_state *plane_state);
-       void (*disable_plane)(struct intel_plane *plane,
-                             const struct intel_crtc_state *crtc_state);
+       /* Write all self-arming plane registers */
+       void (*update_arm)(struct intel_plane *plane,
+                          const struct intel_crtc_state *crtc_state,
+                          const struct intel_plane_state *plane_state);
+       /* Disable the plane, must arm */
+       void (*disable_arm)(struct intel_plane *plane,
+                           const struct intel_crtc_state *crtc_state);
        bool (*get_hw_state)(struct intel_plane *plane, enum pipe *pipe);
        int (*check_plane)(struct intel_crtc_state *crtc_state,
                           struct intel_plane_state *plane_state);
 
                                  gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
 }
 
+/* TODO: split into noarm+arm pair */
 static void
-vlv_sprite_update(struct intel_plane *plane,
-                 const struct intel_crtc_state *crtc_state,
-                 const struct intel_plane_state *plane_state)
+vlv_sprite_update_arm(struct intel_plane *plane,
+                     const struct intel_crtc_state *crtc_state,
+                     const struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum pipe pipe = plane->pipe;
 }
 
 static void
-vlv_sprite_disable(struct intel_plane *plane,
-                  const struct intel_crtc_state *crtc_state)
+vlv_sprite_disable_arm(struct intel_plane *plane,
+                      const struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum pipe pipe = plane->pipe;
        i++;
 }
 
+/* TODO: split into noarm+arm pair */
 static void
-ivb_sprite_update(struct intel_plane *plane,
-                 const struct intel_crtc_state *crtc_state,
-                 const struct intel_plane_state *plane_state)
+ivb_sprite_update_arm(struct intel_plane *plane,
+                     const struct intel_crtc_state *crtc_state,
+                     const struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum pipe pipe = plane->pipe;
 }
 
 static void
-ivb_sprite_disable(struct intel_plane *plane,
-                  const struct intel_crtc_state *crtc_state)
+ivb_sprite_disable_arm(struct intel_plane *plane,
+                      const struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum pipe pipe = plane->pipe;
 }
 
 static void
-g4x_sprite_update(struct intel_plane *plane,
-                 const struct intel_crtc_state *crtc_state,
-                 const struct intel_plane_state *plane_state)
+g4x_sprite_update_arm(struct intel_plane *plane,
+                     const struct intel_crtc_state *crtc_state,
+                     const struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum pipe pipe = plane->pipe;
 }
 
 static void
-g4x_sprite_disable(struct intel_plane *plane,
-                  const struct intel_crtc_state *crtc_state)
+g4x_sprite_disable_arm(struct intel_plane *plane,
+                      const struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum pipe pipe = plane->pipe;
                return plane;
 
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-               plane->update_plane = vlv_sprite_update;
-               plane->disable_plane = vlv_sprite_disable;
+               plane->update_arm = vlv_sprite_update_arm;
+               plane->disable_arm = vlv_sprite_disable_arm;
                plane->get_hw_state = vlv_sprite_get_hw_state;
                plane->check_plane = vlv_sprite_check;
                plane->max_stride = i965_plane_max_stride;
 
                plane_funcs = &vlv_sprite_funcs;
        } else if (DISPLAY_VER(dev_priv) >= 7) {
-               plane->update_plane = ivb_sprite_update;
-               plane->disable_plane = ivb_sprite_disable;
+               plane->update_arm = ivb_sprite_update_arm;
+               plane->disable_arm = ivb_sprite_disable_arm;
                plane->get_hw_state = ivb_sprite_get_hw_state;
                plane->check_plane = g4x_sprite_check;
 
 
                plane_funcs = &snb_sprite_funcs;
        } else {
-               plane->update_plane = g4x_sprite_update;
-               plane->disable_plane = g4x_sprite_disable;
+               plane->update_arm = g4x_sprite_update_arm;
+               plane->disable_arm = g4x_sprite_disable_arm;
                plane->get_hw_state = g4x_sprite_get_hw_state;
                plane->check_plane = g4x_sprite_check;
                plane->max_stride = g4x_sprite_max_stride;
 
 }
 
 static void
-skl_disable_plane(struct intel_plane *plane,
-                 const struct intel_crtc_state *crtc_state)
+skl_plane_disable_arm(struct intel_plane *plane,
+                     const struct intel_crtc_state *crtc_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        enum plane_id plane_id = plane->id;
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
+/* TODO: split into noarm+arm pair */
 static void
-skl_update_plane(struct intel_plane *plane,
-                const struct intel_crtc_state *crtc_state,
-                const struct intel_plane_state *plane_state)
+skl_plane_update_arm(struct intel_plane *plane,
+                    const struct intel_crtc_state *crtc_state,
+                    const struct intel_plane_state *plane_state)
 {
        int color_plane = 0;
 
        }
 
        plane->max_stride = skl_plane_max_stride;
-       plane->update_plane = skl_update_plane;
-       plane->disable_plane = skl_disable_plane;
+       plane->update_arm = skl_plane_update_arm;
+       plane->disable_arm = skl_plane_disable_arm;
        plane->get_hw_state = skl_plane_get_hw_state;
        plane->check_plane = skl_plane_check;
 
 
 
 /* plane updates */
 
-TRACE_EVENT(intel_update_plane,
+TRACE_EVENT(intel_plane_update_noarm,
            TP_PROTO(struct drm_plane *plane, struct intel_crtc *crtc),
            TP_ARGS(plane, crtc),
 
                      DRM_RECT_ARG((const struct drm_rect *)__entry->dst))
 );
 
-TRACE_EVENT(intel_disable_plane,
+TRACE_EVENT(intel_plane_update_arm,
+           TP_PROTO(struct drm_plane *plane, struct intel_crtc *crtc),
+           TP_ARGS(plane, crtc),
+
+           TP_STRUCT__entry(
+                            __field(enum pipe, pipe)
+                            __field(u32, frame)
+                            __field(u32, scanline)
+                            __array(int, src, 4)
+                            __array(int, dst, 4)
+                            __string(name, plane->name)
+                            ),
+
+           TP_fast_assign(
+                          __assign_str(name, plane->name);
+                          __entry->pipe = crtc->pipe;
+                          __entry->frame = intel_crtc_get_vblank_counter(crtc);
+                          __entry->scanline = intel_get_crtc_scanline(crtc);
+                          memcpy(__entry->src, &plane->state->src, sizeof(__entry->src));
+                          memcpy(__entry->dst, &plane->state->dst, sizeof(__entry->dst));
+                          ),
+
+           TP_printk("pipe %c, plane %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT,
+                     pipe_name(__entry->pipe), __get_str(name),
+                     __entry->frame, __entry->scanline,
+                     DRM_RECT_FP_ARG((const struct drm_rect *)__entry->src),
+                     DRM_RECT_ARG((const struct drm_rect *)__entry->dst))
+);
+
+TRACE_EVENT(intel_plane_disable_arm,
            TP_PROTO(struct drm_plane *plane, struct intel_crtc *crtc),
            TP_ARGS(plane, crtc),