aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_crtc.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c123
1 files changed, 48 insertions, 75 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];