summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/exynos/exynos_drm_drv.c
diff options
context:
space:
mode:
authorGustavo Padovan <gustavo.padovan@collabora.co.uk>2015-08-15 13:26:18 -0300
committerInki Dae <daeinki@gmail.com>2015-08-31 00:27:38 +0900
commitc4533665d819271dad890440b887776ac3d5f265 (patch)
treea4c545175fba766dfdbabf21487f6347d869db54 /drivers/gpu/drm/exynos/exynos_drm_drv.c
parenta379df19356de97afdca37c4e8f5e8729215d6ea (diff)
downloadlwn-c4533665d819271dad890440b887776ac3d5f265.tar.gz
lwn-c4533665d819271dad890440b887776ac3d5f265.zip
drm/exynos: wait all planes updates to finish
Add infrastructure to wait for all planes updates to finish by using an atomic_t variable to track how many pending updates we are waiting plus a wait_queue for the wait part. It also changes vblank behaviour and keeps it enabled for all types of updates Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk> Signed-off-by: Inki Dae <inki.dae@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/exynos/exynos_drm_drv.c')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 898591792b12..1350c8e2d587 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -45,11 +45,37 @@ struct exynos_atomic_commit {
u32 crtcs;
};
+static void exynos_atomic_wait_for_commit(struct drm_atomic_state *state)
+{
+ struct drm_crtc_state *crtc_state;
+ struct drm_crtc *crtc;
+ int i, ret;
+
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+ if (!crtc->state->enable)
+ continue;
+
+ ret = drm_crtc_vblank_get(crtc);
+ if (ret)
+ continue;
+
+ exynos_drm_crtc_wait_pending_update(exynos_crtc);
+ drm_crtc_vblank_put(crtc);
+ }
+}
+
static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit)
{
struct drm_device *dev = commit->dev;
struct exynos_drm_private *priv = dev->dev_private;
struct drm_atomic_state *state = commit->state;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_plane_state *plane_state;
+ struct drm_crtc_state *crtc_state;
+ int i;
drm_atomic_helper_commit_modeset_disables(dev, state);
@@ -63,9 +89,25 @@ static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit)
* have the relevant clocks enabled to perform the update.
*/
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
+ atomic_set(&exynos_crtc->pending_update, 0);
+ }
+
+ for_each_plane_in_state(state, plane, plane_state, i) {
+ struct exynos_drm_crtc *exynos_crtc =
+ to_exynos_crtc(plane->crtc);
+
+ if (!plane->crtc)
+ continue;
+
+ atomic_inc(&exynos_crtc->pending_update);
+ }
+
drm_atomic_helper_commit_planes(dev, state);
- drm_atomic_helper_wait_for_vblanks(dev, state);
+ exynos_atomic_wait_for_commit(state);
drm_atomic_helper_cleanup_planes(dev, state);