Skip to content

Commit

Permalink
drm/mali-dp: Fix malidp_atomic_commit_hw_done() for event sending.
Browse files Browse the repository at this point in the history
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.

Reported-by: Alexandru-Cosmin Gheorghe <alexandru-cosmin.gheorghe@arm.com>
Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
  • Loading branch information
Liviu Dudau authored and Liviu Dudau committed Mar 14, 2018
1 parent f043781 commit d862b2d
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 18 deletions.
32 changes: 17 additions & 15 deletions drivers/gpu/drm/arm/malidp_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/arm/malidp_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
12 changes: 9 additions & 3 deletions drivers/gpu/drm/arm/malidp_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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);
Expand Down

0 comments on commit d862b2d

Please sign in to comment.