Skip to content

Commit b1ce7fe

Browse files
committed
drm: renesas: shmobile: Wait for page flip when turning 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. Reviewed-by: Laurent Pinchart <[email protected]> Signed-off-by: Geert Uytterhoeven <[email protected]> Link: https://lore.kernel.org/r/c97d5859c43fa36043c61de28d67688ebe345092.1694767209.git.geert+renesas@glider.be
1 parent a87e315 commit b1ce7fe

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,40 @@ void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc)
5050
scrtc->event = NULL;
5151
if (event) {
5252
drm_crtc_send_vblank_event(&scrtc->base, event);
53+
wake_up(&scrtc->flip_wait);
5354
drm_crtc_vblank_put(&scrtc->base);
5455
}
5556
spin_unlock_irqrestore(&dev->event_lock, flags);
5657
}
5758

59+
static bool shmob_drm_crtc_page_flip_pending(struct shmob_drm_crtc *scrtc)
60+
{
61+
struct drm_device *dev = scrtc->base.dev;
62+
unsigned long flags;
63+
bool pending;
64+
65+
spin_lock_irqsave(&dev->event_lock, flags);
66+
pending = scrtc->event != NULL;
67+
spin_unlock_irqrestore(&dev->event_lock, flags);
68+
69+
return pending;
70+
}
71+
72+
static void shmob_drm_crtc_wait_page_flip(struct shmob_drm_crtc *scrtc)
73+
{
74+
struct drm_crtc *crtc = &scrtc->base;
75+
struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
76+
77+
if (wait_event_timeout(scrtc->flip_wait,
78+
!shmob_drm_crtc_page_flip_pending(scrtc),
79+
msecs_to_jiffies(50)))
80+
return;
81+
82+
dev_warn(sdev->dev, "page flip timeout\n");
83+
84+
shmob_drm_crtc_finish_page_flip(scrtc);
85+
}
86+
5887
/* -----------------------------------------------------------------------------
5988
* CRTC
6089
*/
@@ -253,6 +282,12 @@ static void shmob_drm_crtc_stop(struct shmob_drm_crtc *scrtc)
253282
if (!scrtc->started)
254283
return;
255284

285+
/*
286+
* Wait for page flip completion before stopping the CRTC as userspace
287+
* expects page flips to eventually complete.
288+
*/
289+
shmob_drm_crtc_wait_page_flip(scrtc);
290+
256291
/* Stop the LCDC. */
257292
shmob_drm_crtc_start_stop(scrtc, false);
258293

@@ -463,6 +498,8 @@ int shmob_drm_crtc_create(struct shmob_drm_device *sdev)
463498
unsigned int i;
464499
int ret;
465500

501+
init_waitqueue_head(&sdev->crtc.flip_wait);
502+
466503
sdev->crtc.dpms = DRM_MODE_DPMS_OFF;
467504

468505
primary = shmob_drm_plane_create(sdev, DRM_PLANE_TYPE_PRIMARY, 0);

drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <drm/drm_connector.h>
1515
#include <drm/drm_encoder.h>
1616

17+
#include <linux/wait.h>
18+
1719
#include <video/videomode.h>
1820

1921
struct drm_pending_vblank_event;
@@ -24,6 +26,7 @@ struct shmob_drm_crtc {
2426
struct drm_crtc base;
2527

2628
struct drm_pending_vblank_event *event;
29+
wait_queue_head_t flip_wait;
2730
int dpms;
2831

2932
const struct shmob_drm_format_info *format;

0 commit comments

Comments
 (0)