aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vc4/vc4_crtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_crtc.c')
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c66
1 files changed, 43 insertions, 23 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 403bbd5f99a9..a12cc7ea99b6 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -520,6 +520,34 @@ static void vc4_crtc_disable(struct drm_crtc *crtc)
520 SCALER_DISPSTATX_EMPTY); 520 SCALER_DISPSTATX_EMPTY);
521} 521}
522 522
523static void vc4_crtc_update_dlist(struct drm_crtc *crtc)
524{
525 struct drm_device *dev = crtc->dev;
526 struct vc4_dev *vc4 = to_vc4_dev(dev);
527 struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
528 struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
529
530 if (crtc->state->event) {
531 unsigned long flags;
532
533 crtc->state->event->pipe = drm_crtc_index(crtc);
534
535 WARN_ON(drm_crtc_vblank_get(crtc) != 0);
536
537 spin_lock_irqsave(&dev->event_lock, flags);
538 vc4_crtc->event = crtc->state->event;
539 crtc->state->event = NULL;
540
541 HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
542 vc4_state->mm.start);
543
544 spin_unlock_irqrestore(&dev->event_lock, flags);
545 } else {
546 HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
547 vc4_state->mm.start);
548 }
549}
550
523static void vc4_crtc_enable(struct drm_crtc *crtc) 551static void vc4_crtc_enable(struct drm_crtc *crtc)
524{ 552{
525 struct drm_device *dev = crtc->dev; 553 struct drm_device *dev = crtc->dev;
@@ -530,6 +558,12 @@ static void vc4_crtc_enable(struct drm_crtc *crtc)
530 558
531 require_hvs_enabled(dev); 559 require_hvs_enabled(dev);
532 560
561 /* Enable vblank irq handling before crtc is started otherwise
562 * drm_crtc_get_vblank() fails in vc4_crtc_update_dlist().
563 */
564 drm_crtc_vblank_on(crtc);
565 vc4_crtc_update_dlist(crtc);
566
533 /* Turn on the scaler, which will wait for vstart to start 567 /* Turn on the scaler, which will wait for vstart to start
534 * compositing. 568 * compositing.
535 */ 569 */
@@ -541,9 +575,6 @@ static void vc4_crtc_enable(struct drm_crtc *crtc)
541 /* Turn on the pixel valve, which will emit the vstart signal. */ 575 /* Turn on the pixel valve, which will emit the vstart signal. */
542 CRTC_WRITE(PV_V_CONTROL, 576 CRTC_WRITE(PV_V_CONTROL,
543 CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN); 577 CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN);
544
545 /* Enable vblank irq handling after crtc is started. */
546 drm_crtc_vblank_on(crtc);
547} 578}
548 579
549static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, 580static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -598,7 +629,6 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
598{ 629{
599 struct drm_device *dev = crtc->dev; 630 struct drm_device *dev = crtc->dev;
600 struct vc4_dev *vc4 = to_vc4_dev(dev); 631 struct vc4_dev *vc4 = to_vc4_dev(dev);
601 struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
602 struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); 632 struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
603 struct drm_plane *plane; 633 struct drm_plane *plane;
604 bool debug_dump_regs = false; 634 bool debug_dump_regs = false;
@@ -620,25 +650,15 @@ static void vc4_crtc_atomic_flush(struct drm_crtc *crtc,
620 650
621 WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm.size); 651 WARN_ON_ONCE(dlist_next - dlist_start != vc4_state->mm.size);
622 652
623 if (crtc->state->event) { 653 /* Only update DISPLIST if the CRTC was already running and is not
624 unsigned long flags; 654 * being disabled.
625 655 * vc4_crtc_enable() takes care of updating the dlist just after
626 crtc->state->event->pipe = drm_crtc_index(crtc); 656 * re-enabling VBLANK interrupts and before enabling the engine.
627 657 * If the CRTC is being disabled, there's no point in updating this
628 WARN_ON(drm_crtc_vblank_get(crtc) != 0); 658 * information.
629 659 */
630 spin_lock_irqsave(&dev->event_lock, flags); 660 if (crtc->state->active && old_state->active)
631 vc4_crtc->event = crtc->state->event; 661 vc4_crtc_update_dlist(crtc);
632 crtc->state->event = NULL;
633
634 HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
635 vc4_state->mm.start);
636
637 spin_unlock_irqrestore(&dev->event_lock, flags);
638 } else {
639 HVS_WRITE(SCALER_DISPLISTX(vc4_crtc->channel),
640 vc4_state->mm.start);
641 }
642 662
643 if (debug_dump_regs) { 663 if (debug_dump_regs) {
644 DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc)); 664 DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));