aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiviu Dudau <Liviu.Dudau@arm.com>2018-03-01 11:38:02 -0500
committerLiviu Dudau <Liviu.Dudau@arm.com>2018-03-14 07:38:02 -0400
commitd862b2d622530d14072f3ae417a0525fb7361410 (patch)
tree6ce41110c918b40d2cfab3ee41310c126d14f6ad
parentf0437819ad82088d4a07732222912345b5b98767 (diff)
drm/mali-dp: Fix malidp_atomic_commit_hw_done() for event sending.
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>
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.c32
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.h1
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.c12
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)
185 185
186static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state) 186static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state)
187{ 187{
188 struct drm_pending_vblank_event *event;
189 struct drm_device *drm = state->dev; 188 struct drm_device *drm = state->dev;
190 struct malidp_drm *malidp = drm->dev_private; 189 struct malidp_drm *malidp = drm->dev_private;
191 190
192 if (malidp->crtc.enabled) { 191 malidp->event = malidp->crtc.state->event;
193 /* only set config_valid if the CRTC is enabled */ 192 malidp->crtc.state->event = NULL;
194 if (malidp_set_and_wait_config_valid(drm))
195 DRM_DEBUG_DRIVER("timed out waiting for updated configuration\n");
196 }
197 193
198 event = malidp->crtc.state->event; 194 if (malidp->crtc.state->active) {
199 if (event) { 195 /*
200 malidp->crtc.state->event = NULL; 196 * if we have an event to deliver to userspace, make sure
197 * the vblank is enabled as we are sending it from the IRQ
198 * handler.
199 */
200 if (malidp->event)
201 drm_crtc_vblank_get(&malidp->crtc);
201 202
203 /* only set config_valid if the CRTC is enabled */
204 if (malidp_set_and_wait_config_valid(drm) < 0)
205 DRM_DEBUG_DRIVER("timed out waiting for updated configuration\n");
206 } else if (malidp->event) {
207 /* CRTC inactive means vblank IRQ is disabled, send event directly */
202 spin_lock_irq(&drm->event_lock); 208 spin_lock_irq(&drm->event_lock);
203 if (drm_crtc_vblank_get(&malidp->crtc) == 0) 209 drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
204 drm_crtc_arm_vblank_event(&malidp->crtc, event); 210 malidp->event = NULL;
205 else
206 drm_crtc_send_vblank_event(&malidp->crtc, event);
207 spin_unlock_irq(&drm->event_lock); 211 spin_unlock_irq(&drm->event_lock);
208 } 212 }
209 drm_atomic_helper_commit_hw_done(state); 213 drm_atomic_helper_commit_hw_done(state);
@@ -232,8 +236,6 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state)
232 236
233 malidp_atomic_commit_hw_done(state); 237 malidp_atomic_commit_hw_done(state);
234 238
235 drm_atomic_helper_wait_for_vblanks(drm, state);
236
237 pm_runtime_put(drm->dev); 239 pm_runtime_put(drm->dev);
238 240
239 drm_atomic_helper_cleanup_planes(drm, state); 241 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 {
22 struct malidp_hw_device *dev; 22 struct malidp_hw_device *dev;
23 struct drm_crtc crtc; 23 struct drm_crtc crtc;
24 wait_queue_head_t wq; 24 wait_queue_head_t wq;
25 struct drm_pending_vblank_event *event;
25 atomic_t config_valid; 26 atomic_t config_valid;
26 u32 core_id; 27 u32 core_id;
27}; 28};
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)
782 /* first handle the config valid IRQ */ 782 /* first handle the config valid IRQ */
783 dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS); 783 dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS);
784 if (dc_status & hw->map.dc_irq_map.vsync_irq) { 784 if (dc_status & hw->map.dc_irq_map.vsync_irq) {
785 /* we have a page flip event */
786 atomic_set(&malidp->config_valid, 1);
787 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status); 785 malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status);
786 /* do we have a page flip event? */
787 if (malidp->event != NULL) {
788 spin_lock(&drm->event_lock);
789 drm_crtc_send_vblank_event(&malidp->crtc, malidp->event);
790 malidp->event = NULL;
791 spin_unlock(&drm->event_lock);
792 }
793 atomic_set(&malidp->config_valid, 1);
788 ret = IRQ_WAKE_THREAD; 794 ret = IRQ_WAKE_THREAD;
789 } 795 }
790 796
@@ -794,7 +800,7 @@ static irqreturn_t malidp_de_irq(int irq, void *arg)
794 800
795 mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ); 801 mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ);
796 status &= mask; 802 status &= mask;
797 if (status & de->vsync_irq) 803 if ((status & de->vsync_irq) && malidp->crtc.enabled)
798 drm_crtc_handle_vblank(&malidp->crtc); 804 drm_crtc_handle_vblank(&malidp->crtc);
799 805
800 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status); 806 malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status);