diff options
Diffstat (limited to 'drivers/gpu/drm/vc4/vc4_crtc.c')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_crtc.c | 66 |
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 | ||
523 | static 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 | |||
523 | static void vc4_crtc_enable(struct drm_crtc *crtc) | 551 | static 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 | ||
549 | static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, | 580 | static 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)); |