summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorLiu Ying <victor.liu@nxp.com>2019-09-23 11:22:42 +0800
committerLiu Ying <victor.liu@nxp.com>2019-09-26 11:11:12 +0800
commitcfce49838e9fb15cc5470a0864ebf28eed99ed3d (patch)
treec0014848bfb4aede2d8a35f013e1cf1d40224997 /drivers/gpu
parent1e5f771cddf867afdb6da1dca3cc601fdfff4bb5 (diff)
MLK-22653-4 drm/imx: dpu: crtc: Precisely send vbland event if CRTC is active
If CRTC is active, we should send vblank event in vblank interrupt handler to make sure it's sent precisely. This patch caches the event to be sent at dpu_crtc->event in the ->atomic_enable() and the ->atomic_flush() callbacks and finally sends it out in dpu_vbl_irq_handler(). Since we rely on the interrupt handler to send the event, we call drm_crtc_vblank_get() to get a vblank refcount to guarantee the interrupt is enabled when caching the event in dpu_crtc_queue_state_event() and call drm_crtc_vblank_put() to drop a vblank refcount in the interrupt handler. Signed-off-by: Liu Ying <victor.liu@nxp.com> (cherry picked from commit c5f325790615eb16fe5a448e4b0afa122a33c23e)
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/imx/dpu/dpu-crtc.c47
-rw-r--r--drivers/gpu/drm/imx/dpu/dpu-crtc.h3
2 files changed, 32 insertions, 18 deletions
diff --git a/drivers/gpu/drm/imx/dpu/dpu-crtc.c b/drivers/gpu/drm/imx/dpu/dpu-crtc.c
index a6f11ed56e76..eb124d4d32ef 100644
--- a/drivers/gpu/drm/imx/dpu/dpu-crtc.c
+++ b/drivers/gpu/drm/imx/dpu/dpu-crtc.c
@@ -45,6 +45,20 @@ alloc_dpu_plane_states(struct dpu_crtc *dpu_crtc)
return states;
}
+static void dpu_crtc_queue_state_event(struct drm_crtc *crtc)
+{
+ struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
+
+ spin_lock_irq(&crtc->dev->event_lock);
+ if (crtc->state->event) {
+ WARN_ON(drm_crtc_vblank_get(crtc));
+ WARN_ON(dpu_crtc->event);
+ dpu_crtc->event = crtc->state->event;
+ crtc->state->event = NULL;
+ }
+ spin_unlock_irq(&crtc->dev->event_lock);
+}
+
struct dpu_plane_state **
crtc_state_get_dpu_plane_states(struct drm_crtc_state *state)
{
@@ -240,13 +254,7 @@ static void dpu_crtc_atomic_enable(struct drm_crtc *crtc,
disable_irq(aux_dpu_crtc->dec_shdld_irq);
}
- if (crtc->state->event) {
- spin_lock_irq(&crtc->dev->event_lock);
- drm_crtc_send_vblank_event(crtc, crtc->state->event);
- spin_unlock_irq(&crtc->dev->event_lock);
-
- crtc->state->event = NULL;
- }
+ dpu_crtc_queue_state_event(crtc);
if (dcstate->use_pc) {
framegen_wait_for_secondary_syncup(dpu_crtc->m_fg);
@@ -313,13 +321,12 @@ static void dpu_crtc_atomic_disable(struct drm_crtc *crtc,
drm_crtc_vblank_off(crtc);
+ spin_lock_irq(&crtc->dev->event_lock);
if (crtc->state->event && !crtc->state->active) {
- spin_lock_irq(&crtc->dev->event_lock);
drm_crtc_send_vblank_event(crtc, crtc->state->event);
- spin_unlock_irq(&crtc->dev->event_lock);
-
crtc->state->event = NULL;
}
+ spin_unlock_irq(&crtc->dev->event_lock);
}
static void dpu_drm_crtc_reset(struct drm_crtc *crtc)
@@ -431,8 +438,18 @@ static const struct drm_crtc_funcs dpu_crtc_funcs = {
static irqreturn_t dpu_vbl_irq_handler(int irq, void *dev_id)
{
struct dpu_crtc *dpu_crtc = dev_id;
+ struct drm_crtc *crtc = &dpu_crtc->base;
+ unsigned long flags;
- drm_crtc_handle_vblank(&dpu_crtc->base);
+ drm_crtc_handle_vblank(crtc);
+
+ spin_lock_irqsave(&crtc->dev->event_lock, flags);
+ if (dpu_crtc->event) {
+ drm_crtc_send_vblank_event(crtc, dpu_crtc->event);
+ dpu_crtc->event = NULL;
+ drm_crtc_vblank_put(crtc);
+ }
+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
return IRQ_HANDLED;
}
@@ -772,13 +789,7 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc,
}
}
- if (crtc->state->event) {
- spin_lock_irq(&crtc->dev->event_lock);
- drm_crtc_send_vblank_event(crtc, crtc->state->event);
- spin_unlock_irq(&crtc->dev->event_lock);
-
- crtc->state->event = NULL;
- }
+ dpu_crtc_queue_state_event(crtc);
} else if (!crtc->state->active) {
if (old_dcstate->use_pc) {
if (extdst_is_master(ed)) {
diff --git a/drivers/gpu/drm/imx/dpu/dpu-crtc.h b/drivers/gpu/drm/imx/dpu/dpu-crtc.h
index 2e3a283cb68c..c4be53926e2b 100644
--- a/drivers/gpu/drm/imx/dpu/dpu-crtc.h
+++ b/drivers/gpu/drm/imx/dpu/dpu-crtc.h
@@ -15,6 +15,7 @@
#ifndef _DPU_CRTC_H_
#define _DPU_CRTC_H_
+#include <drm/drm_vblank.h>
#include <video/dpu.h>
#include "dpu-plane.h"
#include "imx-drm.h"
@@ -77,6 +78,8 @@ struct dpu_crtc {
struct completion crc_shdld_done;
struct completion aux_crc_done;
+ struct drm_pending_vblank_event *event;
+
u32 crc_red;
u32 crc_green;
u32 crc_blue;