aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2015-02-18 06:21:56 -0500
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2015-03-03 09:16:04 -0500
commit36693f3c3254d9361095f6b225d5e69bd8da5c32 (patch)
tree89e80dd9bf956eb9dea66f40d39ffa11463967c2
parent17f6b8a0270f7a40b3dbe07dbcb6cb7f67ce570a (diff)
drm: rcar-du: Wait for page flip completion when turning the CRTC off
Turning a CRTC off will prevent a queued page flip from ever completing, potentially confusing userspace. Wait for queued page flips to complete before turning the CRTC off to avoid this. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c35
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.h3
2 files changed, 38 insertions, 0 deletions
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index e0562f2b3261..7f5ae0269a61 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -300,11 +300,39 @@ static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
300 300
301 spin_lock_irqsave(&dev->event_lock, flags); 301 spin_lock_irqsave(&dev->event_lock, flags);
302 drm_send_vblank_event(dev, rcrtc->index, event); 302 drm_send_vblank_event(dev, rcrtc->index, event);
303 wake_up(&rcrtc->flip_wait);
303 spin_unlock_irqrestore(&dev->event_lock, flags); 304 spin_unlock_irqrestore(&dev->event_lock, flags);
304 305
305 drm_vblank_put(dev, rcrtc->index); 306 drm_vblank_put(dev, rcrtc->index);
306} 307}
307 308
309static bool rcar_du_crtc_page_flip_pending(struct rcar_du_crtc *rcrtc)
310{
311 struct drm_device *dev = rcrtc->crtc.dev;
312 unsigned long flags;
313 bool pending;
314
315 spin_lock_irqsave(&dev->event_lock, flags);
316 pending = rcrtc->event != NULL;
317 spin_unlock_irqrestore(&dev->event_lock, flags);
318
319 return pending;
320}
321
322static void rcar_du_crtc_wait_page_flip(struct rcar_du_crtc *rcrtc)
323{
324 struct rcar_du_device *rcdu = rcrtc->group->dev;
325
326 if (wait_event_timeout(rcrtc->flip_wait,
327 !rcar_du_crtc_page_flip_pending(rcrtc),
328 msecs_to_jiffies(50)))
329 return;
330
331 dev_warn(rcdu->dev, "page flip timeout\n");
332
333 rcar_du_crtc_finish_page_flip(rcrtc);
334}
335
308/* ----------------------------------------------------------------------------- 336/* -----------------------------------------------------------------------------
309 * Start/Stop and Suspend/Resume 337 * Start/Stop and Suspend/Resume
310 */ 338 */
@@ -365,6 +393,11 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
365 if (!rcrtc->started) 393 if (!rcrtc->started)
366 return; 394 return;
367 395
396 /* Wait for page flip completion before stopping the CRTC as userspace
397 * excepts page flips to eventually complete.
398 */
399 rcar_du_crtc_wait_page_flip(rcrtc);
400
368 mutex_lock(&rcrtc->group->planes.lock); 401 mutex_lock(&rcrtc->group->planes.lock);
369 rcrtc->plane->enabled = false; 402 rcrtc->plane->enabled = false;
370 rcar_du_crtc_update_planes(crtc); 403 rcar_du_crtc_update_planes(crtc);
@@ -644,6 +677,8 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
644 return -EPROBE_DEFER; 677 return -EPROBE_DEFER;
645 } 678 }
646 679
680 init_waitqueue_head(&rcrtc->flip_wait);
681
647 rcrtc->group = rgrp; 682 rcrtc->group = rgrp;
648 rcrtc->mmio_offset = mmio_offsets[index]; 683 rcrtc->mmio_offset = mmio_offsets[index];
649 rcrtc->index = index; 684 rcrtc->index = index;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index d2f89f7d2e5e..fb39e040f17b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -15,6 +15,7 @@
15#define __RCAR_DU_CRTC_H__ 15#define __RCAR_DU_CRTC_H__
16 16
17#include <linux/mutex.h> 17#include <linux/mutex.h>
18#include <linux/wait.h>
18 19
19#include <drm/drmP.h> 20#include <drm/drmP.h>
20#include <drm/drm_crtc.h> 21#include <drm/drm_crtc.h>
@@ -32,6 +33,8 @@ struct rcar_du_crtc {
32 bool started; 33 bool started;
33 34
34 struct drm_pending_vblank_event *event; 35 struct drm_pending_vblank_event *event;
36 wait_queue_head_t flip_wait;
37
35 unsigned int outputs; 38 unsigned int outputs;
36 int dpms; 39 int dpms;
37 40