aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2015-05-29 09:01:18 -0400
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2015-06-12 16:30:47 -0400
commit5f741b39dde47c054af78727cce7202fff9f781b (patch)
treee0ba2b0b2f0b4a301b7c23c1439ee80fc0e33237 /drivers
parent6646dfd02985eb67d8dcc00d0d345c8dc40f9925 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c123
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c22
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.h1
3 files changed, 70 insertions, 76 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 8d2bf8565ddd..23d9c928cdc9 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -17,8 +17,6 @@
17 * this program. If not, see <http://www.gnu.org/licenses/>. 17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */ 18 */
19 19
20#include <linux/completion.h>
21
22#include <drm/drm_atomic.h> 20#include <drm/drm_atomic.h>
23#include <drm/drm_atomic_helper.h> 21#include <drm/drm_atomic_helper.h>
24#include <drm/drm_crtc.h> 22#include <drm/drm_crtc.h>
@@ -49,13 +47,10 @@ struct omap_crtc {
49 struct omap_drm_irq vblank_irq; 47 struct omap_drm_irq vblank_irq;
50 struct omap_drm_irq error_irq; 48 struct omap_drm_irq error_irq;
51 49
52 /* pending event */
53 struct drm_pending_vblank_event *event;
54 wait_queue_head_t flip_wait;
55
56 struct completion completion;
57
58 bool ignore_digit_sync_lost; 50 bool ignore_digit_sync_lost;
51
52 bool pending;
53 wait_queue_head_t pending_wait;
59}; 54};
60 55
61/* ----------------------------------------------------------------------------- 56/* -----------------------------------------------------------------------------
@@ -81,6 +76,15 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
81 return omap_crtc->channel; 76 return omap_crtc->channel;
82} 77}
83 78
79int omap_crtc_wait_pending(struct drm_crtc *crtc)
80{
81 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
82
83 return wait_event_timeout(omap_crtc->pending_wait,
84 !omap_crtc->pending,
85 msecs_to_jiffies(50));
86}
87
84/* ----------------------------------------------------------------------------- 88/* -----------------------------------------------------------------------------
85 * DSS Manager Functions 89 * DSS Manager Functions
86 */ 90 */
@@ -255,61 +259,29 @@ static const struct dss_mgr_ops mgr_ops = {
255 259
256static void omap_crtc_complete_page_flip(struct drm_crtc *crtc) 260static void omap_crtc_complete_page_flip(struct drm_crtc *crtc)
257{ 261{
258 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
259 struct drm_pending_vblank_event *event; 262 struct drm_pending_vblank_event *event;
260 struct drm_device *dev = crtc->dev; 263 struct drm_device *dev = crtc->dev;
261 unsigned long flags; 264 unsigned long flags;
262 265
263 spin_lock_irqsave(&dev->event_lock, flags); 266 event = crtc->state->event;
264
265 event = omap_crtc->event;
266 omap_crtc->event = NULL;
267 267
268 if (event) { 268 if (!event)
269 list_del(&event->base.link); 269 return;
270
271 /*
272 * Queue the event for delivery if it's still linked to a file
273 * handle, otherwise just destroy it.
274 */
275 if (event->base.file_priv)
276 drm_crtc_send_vblank_event(crtc, event);
277 else
278 event->base.destroy(&event->base);
279
280 wake_up(&omap_crtc->flip_wait);
281 drm_crtc_vblank_put(crtc);
282 }
283
284 spin_unlock_irqrestore(&dev->event_lock, flags);
285}
286
287static bool omap_crtc_page_flip_pending(struct drm_crtc *crtc)
288{
289 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
290 struct drm_device *dev = crtc->dev;
291 unsigned long flags;
292 bool pending;
293 270
294 spin_lock_irqsave(&dev->event_lock, flags); 271 spin_lock_irqsave(&dev->event_lock, flags);
295 pending = omap_crtc->event != NULL;
296 spin_unlock_irqrestore(&dev->event_lock, flags);
297 272
298 return pending; 273 list_del(&event->base.link);
299}
300 274
301static void omap_crtc_wait_page_flip(struct drm_crtc *crtc) 275 /*
302{ 276 * Queue the event for delivery if it's still linked to a file
303 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 277 * handle, otherwise just destroy it.
304 278 */
305 if (wait_event_timeout(omap_crtc->flip_wait, 279 if (event->base.file_priv)
306 !omap_crtc_page_flip_pending(crtc), 280 drm_crtc_send_vblank_event(crtc, event);
307 msecs_to_jiffies(50))) 281 else
308 return; 282 event->base.destroy(&event->base);
309
310 dev_warn(crtc->dev->dev, "page flip timeout!\n");
311 283
312 omap_crtc_complete_page_flip(crtc); 284 spin_unlock_irqrestore(&dev->event_lock, flags);
313} 285}
314 286
315static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) 287static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
@@ -336,12 +308,19 @@ static void omap_crtc_vblank_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
336 return; 308 return;
337 309
338 DBG("%s: apply done", omap_crtc->name); 310 DBG("%s: apply done", omap_crtc->name);
311
339 __omap_irq_unregister(dev, &omap_crtc->vblank_irq); 312 __omap_irq_unregister(dev, &omap_crtc->vblank_irq);
340 313
341 /* wakeup userspace */ 314 rmb();
315 WARN_ON(!omap_crtc->pending);
316 omap_crtc->pending = false;
317 wmb();
318
319 /* wake up userspace */
342 omap_crtc_complete_page_flip(&omap_crtc->base); 320 omap_crtc_complete_page_flip(&omap_crtc->base);
343 321
344 complete(&omap_crtc->completion); 322 /* wake up omap_atomic_complete */
323 wake_up(&omap_crtc->pending_wait);
345} 324}
346 325
347/* ----------------------------------------------------------------------------- 326/* -----------------------------------------------------------------------------
@@ -375,6 +354,13 @@ static void omap_crtc_enable(struct drm_crtc *crtc)
375 354
376 DBG("%s", omap_crtc->name); 355 DBG("%s", omap_crtc->name);
377 356
357 rmb();
358 WARN_ON(omap_crtc->pending);
359 omap_crtc->pending = true;
360 wmb();
361
362 omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
363
378 drm_crtc_vblank_on(crtc); 364 drm_crtc_vblank_on(crtc);
379} 365}
380 366
@@ -384,7 +370,6 @@ static void omap_crtc_disable(struct drm_crtc *crtc)
384 370
385 DBG("%s", omap_crtc->name); 371 DBG("%s", omap_crtc->name);
386 372
387 omap_crtc_wait_page_flip(crtc);
388 drm_crtc_vblank_off(crtc); 373 drm_crtc_vblank_off(crtc);
389} 374}
390 375
@@ -405,19 +390,6 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
405 390
406static void omap_crtc_atomic_begin(struct drm_crtc *crtc) 391static void omap_crtc_atomic_begin(struct drm_crtc *crtc)
407{ 392{
408 struct drm_pending_vblank_event *event = crtc->state->event;
409 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
410 struct drm_device *dev = crtc->dev;
411 unsigned long flags;
412
413 if (event) {
414 WARN_ON(omap_crtc->event);
415 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
416
417 spin_lock_irqsave(&dev->event_lock, flags);
418 omap_crtc->event = event;
419 spin_unlock_irqrestore(&dev->event_lock, flags);
420 }
421} 393}
422 394
423static void omap_crtc_atomic_flush(struct drm_crtc *crtc) 395static void omap_crtc_atomic_flush(struct drm_crtc *crtc)
@@ -427,14 +399,16 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc)
427 WARN_ON(omap_crtc->vblank_irq.registered); 399 WARN_ON(omap_crtc->vblank_irq.registered);
428 400
429 if (dispc_mgr_is_enabled(omap_crtc->channel)) { 401 if (dispc_mgr_is_enabled(omap_crtc->channel)) {
402
430 DBG("%s: GO", omap_crtc->name); 403 DBG("%s: GO", omap_crtc->name);
431 404
405 rmb();
406 WARN_ON(omap_crtc->pending);
407 omap_crtc->pending = true;
408 wmb();
409
432 dispc_mgr_go(omap_crtc->channel); 410 dispc_mgr_go(omap_crtc->channel);
433 omap_irq_register(crtc->dev, &omap_crtc->vblank_irq); 411 omap_irq_register(crtc->dev, &omap_crtc->vblank_irq);
434
435 WARN_ON(!wait_for_completion_timeout(&omap_crtc->completion,
436 msecs_to_jiffies(100)));
437 reinit_completion(&omap_crtc->completion);
438 } 412 }
439 413
440 crtc->invert_dimensions = !!(crtc->primary->state->rotation & 414 crtc->invert_dimensions = !!(crtc->primary->state->rotation &
@@ -534,8 +508,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
534 508
535 crtc = &omap_crtc->base; 509 crtc = &omap_crtc->base;
536 510
537 init_waitqueue_head(&omap_crtc->flip_wait); 511 init_waitqueue_head(&omap_crtc->pending_wait);
538 init_completion(&omap_crtc->completion);
539 512
540 omap_crtc->channel = channel; 513 omap_crtc->channel = channel;
541 omap_crtc->name = channel_names[channel]; 514 omap_crtc->name = channel_names[channel];
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 50f555530e55..419c2e49adf5 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -66,6 +66,26 @@ struct omap_atomic_state_commit {
66 u32 crtcs; 66 u32 crtcs;
67}; 67};
68 68
69static void omap_atomic_wait_for_completion(struct drm_device *dev,
70 struct drm_atomic_state *old_state)
71{
72 struct drm_crtc_state *old_crtc_state;
73 struct drm_crtc *crtc;
74 unsigned int i;
75 int ret;
76
77 for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
78 if (!crtc->state->enable)
79 continue;
80
81 ret = omap_crtc_wait_pending(crtc);
82
83 if (!ret)
84 dev_warn(dev->dev,
85 "atomic complete timeout (pipe %u)!\n", i);
86 }
87}
88
69static void omap_atomic_complete(struct omap_atomic_state_commit *commit) 89static void omap_atomic_complete(struct omap_atomic_state_commit *commit)
70{ 90{
71 struct drm_device *dev = commit->dev; 91 struct drm_device *dev = commit->dev;
@@ -79,7 +99,7 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit)
79 drm_atomic_helper_commit_planes(dev, old_state); 99 drm_atomic_helper_commit_planes(dev, old_state);
80 drm_atomic_helper_commit_modeset_enables(dev, old_state); 100 drm_atomic_helper_commit_modeset_enables(dev, old_state);
81 101
82 drm_atomic_helper_wait_for_vblanks(dev, old_state); 102 omap_atomic_wait_for_completion(dev, old_state);
83 103
84 drm_atomic_helper_cleanup_planes(dev, old_state); 104 drm_atomic_helper_cleanup_planes(dev, old_state);
85 105
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 0b7a055bf007..ae2df41f216f 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -147,6 +147,7 @@ void omap_crtc_pre_init(void);
147void omap_crtc_pre_uninit(void); 147void omap_crtc_pre_uninit(void);
148struct drm_crtc *omap_crtc_init(struct drm_device *dev, 148struct drm_crtc *omap_crtc_init(struct drm_device *dev,
149 struct drm_plane *plane, enum omap_channel channel, int id); 149 struct drm_plane *plane, enum omap_channel channel, int id);
150int omap_crtc_wait_pending(struct drm_crtc *crtc);
150 151
151struct drm_plane *omap_plane_init(struct drm_device *dev, 152struct drm_plane *omap_plane_init(struct drm_device *dev,
152 int id, enum drm_plane_type type); 153 int id, enum drm_plane_type type);