On asynchronous flip, enable flip done for all the planes on which the
async flip is given by the user. After the last flip_done by the plane
in the atomic_commit send the uevent to the user.

Signed-off-by: Arun R Murthy <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_display_irq.c   | 98 +++++++++++++++++++---
 drivers/gpu/drm/i915/display/skl_universal_plane.c |  2 +-
 2 files changed, 86 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c 
b/drivers/gpu/drm/i915/display/intel_display_irq.c
index 
9adeebb376b189ef72a97e0206e0c24b0f4e7117..4d2e1de27d2003db90fe2408c67e3e56e1d9bfcd
 100644
--- a/drivers/gpu/drm/i915/display/intel_display_irq.c
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
@@ -142,6 +142,44 @@ static void intel_pipe_fault_irq_handler(struct 
intel_display *display,
                  crtc->base.base.id, crtc->base.name, fault_errors);
 }
 
+struct plane_flip_done {
+       u32 flip_done;
+       enum plane_id plane_id;
+};
+static const struct plane_flip_done gen8_plane_flip_done[] = {
+       { .flip_done = GEN9_PIPE_PLANE1_FLIP_DONE, .plane_id = PLANE_1 },
+       { .flip_done = GEN9_PIPE_PLANE2_FLIP_DONE, .plane_id = PLANE_2 },
+       { .flip_done = GEN9_PIPE_PLANE3_FLIP_DONE, .plane_id = PLANE_3 },
+       { .flip_done = GEN9_PIPE_PLANE4_FLIP_DONE, .plane_id = PLANE_4 },
+       { .flip_done = GEN11_PIPE_PLANE5_FLIP_DONE, .plane_id = PLANE_5 },
+       { .flip_done = GEN11_PIPE_PLANE6_FLIP_DONE, .plane_id = PLANE_6 },
+       { .flip_done = GEN11_PIPE_PLANE7_FLIP_DONE, .plane_id = PLANE_7 },
+       {}
+};
+
+static void intel_plane_flip_done_handler(struct intel_display *display,
+                                         const struct plane_flip_done *fd,
+                                         enum pipe pipe, u32 de_iir)
+{
+       struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
+       struct intel_crtc_state *crtc_state =
+               to_intel_crtc_state(crtc->base.state);
+       struct drm_plane *plane;
+       struct drm_plane_state *plane_state;
+       const struct plane_flip_done *flipdone;
+
+       if (!crtc->base.state->async_flip)
+               return;
+
+       drm_for_each_plane_mask(plane, display->drm,
+                               crtc_state->uapi.plane_mask) {
+               plane_state = plane->state;
+               flipdone = &fd[to_intel_plane(plane)->id];
+               if (de_iir & flipdone->flip_done)
+                       complete(&plane_state->flip_done);
+       }
+}
+
 static void
 intel_handle_vblank(struct intel_display *display, enum pipe pipe)
 {
@@ -460,12 +498,27 @@ display_pipe_crc_irq_handler(struct intel_display 
*display,
 #endif
 
 static void flip_done_handler(struct intel_display *display,
-                             enum pipe pipe)
+                             enum pipe pipe, u32 de_iir)
 {
        struct intel_crtc *crtc = intel_crtc_for_pipe(display, pipe);
+       struct intel_crtc_state *crtc_state =
+               to_intel_crtc_state(crtc->base.state);
+       struct drm_plane *plane;
+       struct drm_plane_state *plane_state;
 
        spin_lock(&display->drm->event_lock);
 
+       if (crtc->base.state->async_flip) {
+               drm_for_each_plane_mask(plane, display->drm,
+                                       crtc_state->uapi.plane_mask) {
+                       plane_state = plane->state;
+
+                       /* There are some pending flip done in this pipe */
+                       if (!completion_done(&plane_state->flip_done))
+                               return;
+               }
+       }
+
        if (crtc->flip_done_event) {
                trace_intel_crtc_flip_done(crtc);
                drm_crtc_send_vblank_event(&crtc->base, crtc->flip_done_event);
@@ -657,7 +710,7 @@ void valleyview_pipestat_irq_handler(struct intel_display 
*display,
                        intel_handle_vblank(display, pipe);
 
                if (pipe_stats[pipe] & PLANE_FLIP_DONE_INT_STATUS_VLV)
-                       flip_done_handler(display, pipe);
+                       flip_done_handler(display, pipe, pipe_stats[pipe]);
 
                if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS)
                        i9xx_pipe_crc_irq_handler(display, pipe);
@@ -916,7 +969,7 @@ static void _ilk_display_irq_handler(struct intel_display 
*display, u32 de_iir)
                        intel_handle_vblank(display, pipe);
 
                if (de_iir & DE_PLANE_FLIP_DONE(pipe))
-                       flip_done_handler(display, pipe);
+                       flip_done_handler(display, pipe, de_iir);
 
                if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe))
                        intel_cpu_fifo_underrun_irq_handler(display, pipe);
@@ -977,7 +1030,7 @@ static void _ivb_display_irq_handler(struct intel_display 
*display, u32 de_iir)
                        intel_handle_vblank(display, pipe);
 
                if (de_iir & DE_PLANE_FLIP_DONE_IVB(pipe))
-                       flip_done_handler(display, pipe);
+                       flip_done_handler(display, pipe, de_iir);
        }
 
        /* check event from PCH */
@@ -1368,12 +1421,26 @@ static void gen11_dsi_te_interrupt_handler(struct 
intel_display *display,
        intel_de_rmw(display, DSI_INTR_IDENT_REG(port), 0, 0);
 }
 
-static u32 gen8_de_pipe_flip_done_mask(struct intel_display *display)
+static u32 gen8_de_pipe_flip_done_mask(struct intel_display *display,
+                                      enum pipe pipe)
 {
-       if (DISPLAY_VER(display) >= 9)
-               return GEN9_PIPE_PLANE1_FLIP_DONE;
+       if (DISPLAY_VER(display) >= 11)
+               return (GEN9_PIPE_PLANE1_FLIP_DONE |
+                       GEN9_PIPE_PLANE2_FLIP_DONE |
+                       GEN9_PIPE_PLANE3_FLIP_DONE |
+                       GEN9_PIPE_PLANE4_FLIP_DONE |
+                       GEN11_PIPE_PLANE5_FLIP_DONE |
+                       GEN11_PIPE_PLANE6_FLIP_DONE |
+                       GEN11_PIPE_PLANE7_FLIP_DONE);
+       else if (DISPLAY_VER(display) >= 9)
+               return (GEN9_PIPE_PLANE1_FLIP_DONE |
+                       GEN9_PIPE_PLANE2_FLIP_DONE |
+                       GEN9_PIPE_PLANE3_FLIP_DONE |
+                       GEN9_PIPE_PLANE4_FLIP_DONE);
        else
                return GEN8_PIPE_PRIMARY_FLIP_DONE;
+
+       return 0;
 }
 
 static void gen8_read_and_ack_pch_irqs(struct intel_display *display, u32 
*pch_iir, u32 *pica_iir)
@@ -1504,8 +1571,12 @@ void gen8_de_irq_handler(struct intel_display *display, 
u32 master_ctl)
                if (iir & GEN8_PIPE_VBLANK)
                        intel_handle_vblank(display, pipe);
 
-               if (iir & gen8_de_pipe_flip_done_mask(display))
-                       flip_done_handler(display, pipe);
+               if (iir & gen8_de_pipe_flip_done_mask(display, pipe)) {
+                       intel_plane_flip_done_handler(display,
+                                                     gen8_plane_flip_done,
+                                                     pipe, iir);
+                       flip_done_handler(display, pipe, iir);
+               }
 
                if (HAS_DSB(display)) {
                        if (iir & GEN12_DSB_INT(INTEL_DSB_0))
@@ -2167,8 +2238,7 @@ void gen11_display_irq_reset(struct intel_display 
*display)
 void gen8_irq_power_well_post_enable(struct intel_display *display,
                                     u8 pipe_mask)
 {
-       u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN |
-               gen8_de_pipe_flip_done_mask(display);
+       u32 extra_ier = GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN;
        enum pipe pipe;
 
        spin_lock_irq(&display->irq.lock);
@@ -2178,10 +2248,12 @@ void gen8_irq_power_well_post_enable(struct 
intel_display *display,
                return;
        }
 
-       for_each_pipe_masked(display, pipe, pipe_mask)
+       for_each_pipe_masked(display, pipe, pipe_mask) {
+               extra_ier |= gen8_de_pipe_flip_done_mask(display, pipe);
                irq_init(display, GEN8_DE_PIPE_IRQ_REGS(pipe),
                         display->irq.de_pipe_imr_mask[pipe],
                         ~display->irq.de_pipe_imr_mask[pipe] | extra_ier);
+       }
 
        spin_unlock_irq(&display->irq.lock);
 }
@@ -2364,7 +2436,7 @@ void gen8_de_irq_postinstall(struct intel_display 
*display)
 
        de_pipe_enables = de_pipe_masked |
                GEN8_PIPE_VBLANK | GEN8_PIPE_FIFO_UNDERRUN |
-               gen8_de_pipe_flip_done_mask(display);
+               gen8_de_pipe_flip_done_mask(display, pipe);
 
        de_port_enables = de_port_masked;
        if (display->platform.geminilake || display->platform.broxton)
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 
b3d41705448a28ae7abf7b31775d09db832cb9d6..ac35a7083f31da8f0b0a36dd13554fb24166b429
 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -2927,7 +2927,7 @@ skl_universal_plane_create(struct intel_display *display,
        plane->get_hw_state = skl_plane_get_hw_state;
        plane->check_plane = skl_plane_check;
 
-       if (HAS_ASYNC_FLIPS(display) && plane_id == PLANE_1) {
+       if (HAS_ASYNC_FLIPS(display)) {
                plane->need_async_flip_toggle_wa = IS_DISPLAY_VER(display, 9, 
10);
                plane->async_flip = skl_plane_async_flip;
                plane->enable_flip_done = skl_plane_enable_flip_done;

-- 
2.25.1

Reply via email to