On Mon, Mar 05, 2018 at 06:03:16PM +0000, Liviu Dudau wrote:
> Mali DP hardware has a 'go' bit (config_valid) for making the new scene
> parameters active at the next page flip. The problem with the current
> code is that the driver first sets this bit and then proceeds to wait
> for confirmation from the hardware that the configuration has been
> updated before arming the vblank event. As config_valid is actually
> asserted by the hardware after the vblank event, during the prefetch
> phase, when we get to arming the vblank event we are going to send it
> at the next vblank, in effect halving the vblank rate from the userspace
> perspective.
> 
> Fix it by sending the userspace event from the IRQ handler, when we
> handle the config_valid interrupt, which syncs with the time when the
> hardware is active with the new parameters.
> 
> v2: Brian reminded me that interrupts won't fire when CRTC is off,
> so we need to do the sending ourselves.
> 
> v3: crtc->enabled is the wrong flag to use here, as when we get an
> atomic commit that turns off the CRTC it will still be enabled until
> after the commit is done. Use the crtc->state->active for test.
> 
> Reported-by: Alexandru-Cosmin Gheorghe <alexandru-cosmin.gheor...@arm.com>
> Signed-off-by: Liviu Dudau <liviu.du...@arm.com>
Tested this with Mali DP-650, modetest is able to do page flipping at the
expected frequency. Also, I didn't observe any regressions in the
driver unit tests.

Tested-by: Alexandru Gheorghe <alexandru-cosmin.gheor...@arm.com>  

> ---
>  drivers/gpu/drm/arm/malidp_drv.c | 32 +++++++++++++++++---------------
>  drivers/gpu/drm/arm/malidp_drv.h |  1 +
>  drivers/gpu/drm/arm/malidp_hw.c  | 12 +++++++++---
>  3 files changed, 27 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/arm/malidp_drv.c 
> b/drivers/gpu/drm/arm/malidp_drv.c
> index d88a3b9d59cc..3c628e43bf25 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.c
> +++ b/drivers/gpu/drm/arm/malidp_drv.c
> @@ -185,25 +185,29 @@ static int malidp_set_and_wait_config_valid(struct 
> drm_device *drm)
>  
>  static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state)
>  {
> -     struct drm_pending_vblank_event *event;
>       struct drm_device *drm = state->dev;
>       struct malidp_drm *malidp = drm->dev_private;
>  
> -     if (malidp->crtc.enabled) {
> -             /* only set config_valid if the CRTC is enabled */
> -             if (malidp_set_and_wait_config_valid(drm))
> -                     DRM_DEBUG_DRIVER("timed out waiting for updated 
> configuration\n");
> -     }
> +     malidp->event = malidp->crtc.state->event;
> +     malidp->crtc.state->event = NULL;
>  
> -     event = malidp->crtc.state->event;
> -     if (event) {
> -             malidp->crtc.state->event = NULL;
> +     if (malidp->crtc.state->active) {
> +             /*
> +              * if we have an event to deliver to userspace, make sure
> +              * the vblank is enabled as we are sending it from the IRQ
> +              * handler.
> +              */
> +             if (malidp->event)
> +                     drm_crtc_vblank_get(&malidp->crtc);
>  
> +             /* only set config_valid if the CRTC is enabled */
> +             if (malidp_set_and_wait_config_valid(drm) < 0)
> +                     DRM_DEBUG_DRIVER("timed out waiting for updated 
> configuration\n");
> +     } else if (malidp->event) {
> +             /* CRTC inactive means vblank IRQ is disabled, send event 
> directly */
>               spin_lock_irq(&drm->event_lock);
> -             if (drm_crtc_vblank_get(&malidp->crtc) == 0)
> -                     drm_crtc_arm_vblank_event(&malidp->crtc, event);
> -             else
> -                     drm_crtc_send_vblank_event(&malidp->crtc, event);
> +             drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
> +             malidp->event = NULL;
>               spin_unlock_irq(&drm->event_lock);
>       }
>       drm_atomic_helper_commit_hw_done(state);
> @@ -232,8 +236,6 @@ static void malidp_atomic_commit_tail(struct 
> drm_atomic_state *state)
>  
>       malidp_atomic_commit_hw_done(state);
>  
> -     drm_atomic_helper_wait_for_vblanks(drm, state);
> -
>       pm_runtime_put(drm->dev);
>  
>       drm_atomic_helper_cleanup_planes(drm, state);
> diff --git a/drivers/gpu/drm/arm/malidp_drv.h 
> b/drivers/gpu/drm/arm/malidp_drv.h
> index e0d12c9fc6b8..c2375bb49619 100644
> --- a/drivers/gpu/drm/arm/malidp_drv.h
> +++ b/drivers/gpu/drm/arm/malidp_drv.h
> @@ -22,6 +22,7 @@ struct malidp_drm {
>       struct malidp_hw_device *dev;
>       struct drm_crtc crtc;
>       wait_queue_head_t wq;
> +     struct drm_pending_vblank_event *event;
>       atomic_t config_valid;
>       u32 core_id;
>  };
> diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
> index 2bfb542135ac..8abd335ec313 100644
> --- a/drivers/gpu/drm/arm/malidp_hw.c
> +++ b/drivers/gpu/drm/arm/malidp_hw.c
> @@ -782,9 +782,15 @@ static irqreturn_t malidp_de_irq(int irq, void *arg)
>       /* first handle the config valid IRQ */
>       dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
>       if (dc_status & hw->map.dc_irq_map.vsync_irq) {
> -             /* we have a page flip event */
> -             atomic_set(&malidp->config_valid, 1);
>               malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
> +             /* do we have a page flip event? */
> +             if (malidp->event != NULL) {
> +                     spin_lock(&drm->event_lock);
> +                     drm_crtc_send_vblank_event(&malidp->crtc, 
> malidp->event);
> +                     malidp->event = NULL;
> +                     spin_unlock(&drm->event_lock);
> +             }
> +             atomic_set(&malidp->config_valid, 1);
>               ret = IRQ_WAKE_THREAD;
>       }
>  
> @@ -794,7 +800,7 @@ static irqreturn_t malidp_de_irq(int irq, void *arg)
>  
>       mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
>       status &= mask;
> -     if (status & de->vsync_irq)
> +     if ((status & de->vsync_irq) && malidp->crtc.enabled)
>               drm_crtc_handle_vblank(&malidp->crtc);
>  
>       malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);
> -- 
> 2.16.2
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to