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
