drm: omapdrm: new vblank and event handling

Rework the crtc event/flip_wait system as follows:

- If we enable a crtc (full modeset), we set omap_crtc->pending and
  register vblank irq.

- If we need to set GO bit (page flip), we do the same but also set the
  GO bit.

- On vblank we unregister the irq, clear the 'pending' flag, send vblank
  event to userspace if crtc->state->event != NULL, and wake up
  'pending_wait' wq.

- In omap_atomic_complete() we wait for the 'pending' flag to get reset
  for all enabled crtcs  using 'pending_wait' wq.

The above ensures that we send the events to userspace in vblank, and
that after the wait in omap_atomic_complete() everything for the
affected crtcs has been completed.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 50f5555..419c2e4 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -66,6 +66,26 @@
 	u32 crtcs;
 };
 
+static void omap_atomic_wait_for_completion(struct drm_device *dev,
+					    struct drm_atomic_state *old_state)
+{
+	struct drm_crtc_state *old_crtc_state;
+	struct drm_crtc *crtc;
+	unsigned int i;
+	int ret;
+
+	for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
+		if (!crtc->state->enable)
+			continue;
+
+		ret = omap_crtc_wait_pending(crtc);
+
+		if (!ret)
+			dev_warn(dev->dev,
+				 "atomic complete timeout (pipe %u)!\n", i);
+	}
+}
+
 static void omap_atomic_complete(struct omap_atomic_state_commit *commit)
 {
 	struct drm_device *dev = commit->dev;
@@ -79,7 +99,7 @@
 	drm_atomic_helper_commit_planes(dev, old_state);
 	drm_atomic_helper_commit_modeset_enables(dev, old_state);
 
-	drm_atomic_helper_wait_for_vblanks(dev, old_state);
+	omap_atomic_wait_for_completion(dev, old_state);
 
 	drm_atomic_helper_cleanup_planes(dev, old_state);