summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
diff options
context:
space:
mode:
authorHai Li <hali@codeaurora.org>2015-04-28 19:35:37 -0400
committerRob Clark <robdclark@gmail.com>2015-06-11 13:11:04 -0400
commit0a5c9aad119c4415e14ece4c17cec66aa572e827 (patch)
tree35fb1752d5b0e0a38bec2ced4207d7dc0b2d8770 /drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
parent7eed919a35a1e9289dbbc7b3c89bdb736a2b2a60 (diff)
drm/msm: Use customized function to wait for atomic commit done
MDP FLUSH registers could indicate if the previous flush updates has taken effect at vsync boundary. Making use of this H/W feature can catch the vsync that happened between CRTC atomic_flush and *_wait_for_vblanks, to avoid unnecessary wait. This change allows kms CRTCs to use their own *_wait_for_commit_done functions to wait for FLUSH register cleared at vsync, before commit completion. Signed-off-by: Hai Li <hali@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c')
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index 73afa21822b4..c4bb9d9c7667 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -51,6 +51,11 @@ struct mdp4_crtc {
/* if there is a pending flip, these will be non-null: */
struct drm_pending_vblank_event *event;
+ /* Bits have been flushed at the last commit,
+ * used to decide if a vsync has happened since last commit.
+ */
+ u32 flushed_mask;
+
#define PENDING_CURSOR 0x1
#define PENDING_FLIP 0x2
atomic_t pending;
@@ -93,6 +98,8 @@ static void crtc_flush(struct drm_crtc *crtc)
DBG("%s: flush=%08x", mdp4_crtc->name, flush);
+ mdp4_crtc->flushed_mask = flush;
+
mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush);
}
@@ -537,6 +544,29 @@ static void mdp4_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
crtc_flush(crtc);
}
+static void mdp4_crtc_wait_for_flush_done(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+ struct mdp4_kms *mdp4_kms = get_kms(crtc);
+ int ret;
+
+ ret = drm_crtc_vblank_get(crtc);
+ if (ret)
+ return;
+
+ ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue,
+ !(mdp4_read(mdp4_kms, REG_MDP4_OVERLAY_FLUSH) &
+ mdp4_crtc->flushed_mask),
+ msecs_to_jiffies(50));
+ if (ret <= 0)
+ dev_warn(dev->dev, "vblank time out, crtc=%d\n", mdp4_crtc->id);
+
+ mdp4_crtc->flushed_mask = 0;
+
+ drm_crtc_vblank_put(crtc);
+}
+
uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc)
{
struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
@@ -600,6 +630,15 @@ void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer)
mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel);
}
+void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc)
+{
+ /* wait_for_flush_done is the only case for now.
+ * Later we will have command mode CRTC to wait for
+ * other event.
+ */
+ mdp4_crtc_wait_for_flush_done(crtc);
+}
+
static const char *dma_names[] = {
"DMA_P", "DMA_S", "DMA_E",
};