aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo Padovan <gustavo.padovan@collabora.co.uk>2015-08-15 12:26:18 -0400
committerInki Dae <daeinki@gmail.com>2015-08-30 11:27:38 -0400
commitc4533665d819271dad890440b887776ac3d5f265 (patch)
treea4c545175fba766dfdbabf21487f6347d869db54
parenta379df19356de97afdca37c4e8f5e8729215d6ea (diff)
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>
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c18
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c44
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h4
4 files changed, 61 insertions, 6 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 582e041a9356..d6c2c3f8bc6e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -75,10 +75,7 @@ static void exynos_crtc_atomic_begin(struct drm_crtc *crtc,
75 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 75 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
76 struct drm_plane *plane; 76 struct drm_plane *plane;
77 77
78 if (crtc->state->event) { 78 exynos_crtc->event = crtc->state->event;
79 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
80 exynos_crtc->event = crtc->state->event;
81 }
82 79
83 drm_atomic_crtc_for_each_plane(plane, crtc) { 80 drm_atomic_crtc_for_each_plane(plane, crtc) {
84 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane); 81 struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
@@ -156,6 +153,8 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
156 exynos_crtc->ops = ops; 153 exynos_crtc->ops = ops;
157 exynos_crtc->ctx = ctx; 154 exynos_crtc->ctx = ctx;
158 155
156 init_waitqueue_head(&exynos_crtc->wait_update);
157
159 crtc = &exynos_crtc->base; 158 crtc = &exynos_crtc->base;
160 159
161 private->crtc[pipe] = crtc; 160 private->crtc[pipe] = crtc;
@@ -197,6 +196,13 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe)
197 exynos_crtc->ops->disable_vblank(exynos_crtc); 196 exynos_crtc->ops->disable_vblank(exynos_crtc);
198} 197}
199 198
199void exynos_drm_crtc_wait_pending_update(struct exynos_drm_crtc *exynos_crtc)
200{
201 wait_event_timeout(exynos_crtc->wait_update,
202 (atomic_read(&exynos_crtc->pending_update) == 0),
203 msecs_to_jiffies(50));
204}
205
200void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc, 206void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
201 struct exynos_drm_plane *exynos_plane) 207 struct exynos_drm_plane *exynos_plane)
202{ 208{
@@ -205,10 +211,12 @@ void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
205 211
206 exynos_plane->pending_fb = NULL; 212 exynos_plane->pending_fb = NULL;
207 213
214 if (atomic_dec_and_test(&exynos_crtc->pending_update))
215 wake_up(&exynos_crtc->wait_update);
216
208 spin_lock_irqsave(&crtc->dev->event_lock, flags); 217 spin_lock_irqsave(&crtc->dev->event_lock, flags);
209 if (exynos_crtc->event) { 218 if (exynos_crtc->event) {
210 drm_crtc_send_vblank_event(crtc, exynos_crtc->event); 219 drm_crtc_send_vblank_event(crtc, exynos_crtc->event);
211 drm_crtc_vblank_put(crtc);
212 wake_up(&exynos_crtc->pending_flip_queue); 220 wake_up(&exynos_crtc->pending_flip_queue);
213 } 221 }
214 222
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index 8bedfde2084a..f87d4abda6f7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -25,6 +25,7 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev,
25 void *context); 25 void *context);
26int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe); 26int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe);
27void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe); 27void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe);
28void exynos_drm_crtc_wait_pending_update(struct exynos_drm_crtc *exynos_crtc);
28void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc, 29void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc,
29 struct exynos_drm_plane *exynos_plane); 30 struct exynos_drm_plane *exynos_plane);
30void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb); 31void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb);
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 {
45 u32 crtcs; 45 u32 crtcs;
46}; 46};
47 47
48static void exynos_atomic_wait_for_commit(struct drm_atomic_state *state)
49{
50 struct drm_crtc_state *crtc_state;
51 struct drm_crtc *crtc;
52 int i, ret;
53
54 for_each_crtc_in_state(state, crtc, crtc_state, i) {
55 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
56
57 if (!crtc->state->enable)
58 continue;
59
60 ret = drm_crtc_vblank_get(crtc);
61 if (ret)
62 continue;
63
64 exynos_drm_crtc_wait_pending_update(exynos_crtc);
65 drm_crtc_vblank_put(crtc);
66 }
67}
68
48static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit) 69static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit)
49{ 70{
50 struct drm_device *dev = commit->dev; 71 struct drm_device *dev = commit->dev;
51 struct exynos_drm_private *priv = dev->dev_private; 72 struct exynos_drm_private *priv = dev->dev_private;
52 struct drm_atomic_state *state = commit->state; 73 struct drm_atomic_state *state = commit->state;
74 struct drm_plane *plane;
75 struct drm_crtc *crtc;
76 struct drm_plane_state *plane_state;
77 struct drm_crtc_state *crtc_state;
78 int i;
53 79
54 drm_atomic_helper_commit_modeset_disables(dev, state); 80 drm_atomic_helper_commit_modeset_disables(dev, state);
55 81
@@ -63,9 +89,25 @@ static void exynos_atomic_commit_complete(struct exynos_atomic_commit *commit)
63 * have the relevant clocks enabled to perform the update. 89 * have the relevant clocks enabled to perform the update.
64 */ 90 */
65 91
92 for_each_crtc_in_state(state, crtc, crtc_state, i) {
93 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
94
95 atomic_set(&exynos_crtc->pending_update, 0);
96 }
97
98 for_each_plane_in_state(state, plane, plane_state, i) {
99 struct exynos_drm_crtc *exynos_crtc =
100 to_exynos_crtc(plane->crtc);
101
102 if (!plane->crtc)
103 continue;
104
105 atomic_inc(&exynos_crtc->pending_update);
106 }
107
66 drm_atomic_helper_commit_planes(dev, state); 108 drm_atomic_helper_commit_planes(dev, state);
67 109
68 drm_atomic_helper_wait_for_vblanks(dev, state); 110 exynos_atomic_wait_for_commit(state);
69 111
70 drm_atomic_helper_cleanup_planes(dev, state); 112 drm_atomic_helper_cleanup_planes(dev, state);
71 113
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index b06fbd43b475..7193d94fde3b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -136,6 +136,8 @@ struct exynos_drm_crtc_ops {
136 * this pipe value. 136 * this pipe value.
137 * @enabled: if the crtc is enabled or not 137 * @enabled: if the crtc is enabled or not
138 * @event: vblank event that is currently queued for flip 138 * @event: vblank event that is currently queued for flip
139 * @wait_update: wait all pending planes updates to finish
140 * @pending_update: number of pending plane updates in this crtc
139 * @ops: pointer to callbacks for exynos drm specific functionality 141 * @ops: pointer to callbacks for exynos drm specific functionality
140 * @ctx: A pointer to the crtc's implementation specific context 142 * @ctx: A pointer to the crtc's implementation specific context
141 */ 143 */
@@ -145,6 +147,8 @@ struct exynos_drm_crtc {
145 unsigned int pipe; 147 unsigned int pipe;
146 wait_queue_head_t pending_flip_queue; 148 wait_queue_head_t pending_flip_queue;
147 struct drm_pending_vblank_event *event; 149 struct drm_pending_vblank_event *event;
150 wait_queue_head_t wait_update;
151 atomic_t pending_update;
148 const struct exynos_drm_crtc_ops *ops; 152 const struct exynos_drm_crtc_ops *ops;
149 void *ctx; 153 void *ctx;
150}; 154};