mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-01-11 17:10:13 +00:00
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 <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> Link: https://lore.kernel.org/r/c97d5859c43fa36043c61de28d67688ebe345092.1694767209.git.geert+renesas@glider.be
This commit is contained in:
parent
a87e3159d4
commit
b1ce7fe4c4
@ -50,11 +50,40 @@ void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc)
|
||||
scrtc->event = NULL;
|
||||
if (event) {
|
||||
drm_crtc_send_vblank_event(&scrtc->base, event);
|
||||
wake_up(&scrtc->flip_wait);
|
||||
drm_crtc_vblank_put(&scrtc->base);
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
}
|
||||
|
||||
static bool shmob_drm_crtc_page_flip_pending(struct shmob_drm_crtc *scrtc)
|
||||
{
|
||||
struct drm_device *dev = scrtc->base.dev;
|
||||
unsigned long flags;
|
||||
bool pending;
|
||||
|
||||
spin_lock_irqsave(&dev->event_lock, flags);
|
||||
pending = scrtc->event != NULL;
|
||||
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||
|
||||
return pending;
|
||||
}
|
||||
|
||||
static void shmob_drm_crtc_wait_page_flip(struct shmob_drm_crtc *scrtc)
|
||||
{
|
||||
struct drm_crtc *crtc = &scrtc->base;
|
||||
struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
|
||||
|
||||
if (wait_event_timeout(scrtc->flip_wait,
|
||||
!shmob_drm_crtc_page_flip_pending(scrtc),
|
||||
msecs_to_jiffies(50)))
|
||||
return;
|
||||
|
||||
dev_warn(sdev->dev, "page flip timeout\n");
|
||||
|
||||
shmob_drm_crtc_finish_page_flip(scrtc);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* CRTC
|
||||
*/
|
||||
@ -253,6 +282,12 @@ static void shmob_drm_crtc_stop(struct shmob_drm_crtc *scrtc)
|
||||
if (!scrtc->started)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Wait for page flip completion before stopping the CRTC as userspace
|
||||
* expects page flips to eventually complete.
|
||||
*/
|
||||
shmob_drm_crtc_wait_page_flip(scrtc);
|
||||
|
||||
/* Stop the LCDC. */
|
||||
shmob_drm_crtc_start_stop(scrtc, false);
|
||||
|
||||
@ -463,6 +498,8 @@ int shmob_drm_crtc_create(struct shmob_drm_device *sdev)
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
init_waitqueue_head(&sdev->crtc.flip_wait);
|
||||
|
||||
sdev->crtc.dpms = DRM_MODE_DPMS_OFF;
|
||||
|
||||
primary = shmob_drm_plane_create(sdev, DRM_PLANE_TYPE_PRIMARY, 0);
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include <video/videomode.h>
|
||||
|
||||
struct drm_pending_vblank_event;
|
||||
@ -24,6 +26,7 @@ struct shmob_drm_crtc {
|
||||
struct drm_crtc base;
|
||||
|
||||
struct drm_pending_vblank_event *event;
|
||||
wait_queue_head_t flip_wait;
|
||||
int dpms;
|
||||
|
||||
const struct shmob_drm_format_info *format;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user