diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_crtc.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_crtc.c | 74 |
1 files changed, 55 insertions, 19 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 25593f6aae7d..1b578cad2813 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -24,7 +24,6 @@ #include "intel_display_trace.h" #include "intel_display_types.h" #include "intel_drrs.h" -#include "intel_dsb.h" #include "intel_dsi.h" #include "intel_fifo_underrun.h" #include "intel_pipe_crc.h" @@ -78,8 +77,7 @@ void intel_wait_for_vblank_if_active(struct drm_i915_private *i915, u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc) { - struct drm_device *dev = crtc->base.dev; - struct drm_vblank_crtc *vblank = &dev->vblank[drm_crtc_index(&crtc->base)]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); if (!crtc->active) return 0; @@ -311,8 +309,7 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) crtc->num_scalers = DISPLAY_RUNTIME_INFO(dev_priv)->num_scalers[pipe]; if (DISPLAY_VER(dev_priv) >= 9) - primary = skl_universal_plane_create(dev_priv, pipe, - PLANE_PRIMARY); + primary = skl_universal_plane_create(dev_priv, pipe, PLANE_1); else primary = intel_primary_plane_create(dev_priv, pipe); if (IS_ERR(primary)) { @@ -327,8 +324,7 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) struct intel_plane *plane; if (DISPLAY_VER(dev_priv) >= 9) - plane = skl_universal_plane_create(dev_priv, pipe, - PLANE_SPRITE0 + sprite); + plane = skl_universal_plane_create(dev_priv, pipe, PLANE_2 + sprite); else plane = intel_sprite_plane_create(dev_priv, pipe, sprite); if (IS_ERR(plane)) { @@ -414,8 +410,8 @@ static void intel_crtc_vblank_work(struct kthread_work *base) if (crtc_state->uapi.event) { spin_lock_irq(&crtc->base.dev->event_lock); drm_crtc_send_vblank_event(&crtc->base, crtc_state->uapi.event); - crtc_state->uapi.event = NULL; spin_unlock_irq(&crtc->base.dev->event_lock); + crtc_state->uapi.event = NULL; } trace_intel_crtc_vblank_work_end(crtc); @@ -457,8 +453,8 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, if (!adjusted_mode->crtc_htotal) return 1; - return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock, - 1000 * adjusted_mode->crtc_htotal); + return DIV_ROUND_UP_ULL(mul_u32_u32(usecs, adjusted_mode->crtc_clock), + 1000 * adjusted_mode->crtc_htotal); } /** @@ -500,6 +496,19 @@ void intel_pipe_update_start(struct intel_atomic_state *state, if (intel_crtc_needs_vblank_work(new_crtc_state)) intel_crtc_vblank_work_init(new_crtc_state); + if (state->base.legacy_cursor_update) { + struct intel_plane *plane; + struct intel_plane_state *old_plane_state, *new_plane_state; + int i; + + for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state, + new_plane_state, i) { + if (old_plane_state->uapi.crtc == &crtc->base) + intel_plane_init_cursor_vblank_work(old_plane_state, + new_plane_state); + } + } + intel_vblank_evade_init(old_crtc_state, new_crtc_state, &evade); if (drm_WARN_ON(&dev_priv->drm, drm_crtc_vblank_get(&crtc->base))) @@ -563,6 +572,23 @@ static void dbg_vblank_evade(struct intel_crtc *crtc, ktime_t end) static void dbg_vblank_evade(struct intel_crtc *crtc, ktime_t end) {} #endif +void intel_crtc_arm_vblank_event(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + unsigned long irqflags; + + if (!crtc_state->uapi.event) + return; + + drm_WARN_ON(crtc->base.dev, drm_crtc_vblank_get(&crtc->base) != 0); + + spin_lock_irqsave(&crtc->base.dev->event_lock, irqflags); + drm_crtc_arm_vblank_event(&crtc->base, crtc_state->uapi.event); + spin_unlock_irqrestore(&crtc->base.dev->event_lock, irqflags); + + crtc_state->uapi.event = NULL; +} + /** * intel_pipe_update_end() - end update of a set of display registers * @state: the atomic state @@ -604,16 +630,26 @@ void intel_pipe_update_end(struct intel_atomic_state *state, drm_vblank_work_schedule(&new_crtc_state->vblank_work, drm_crtc_accurate_vblank_count(&crtc->base) + 1, false); - } else if (new_crtc_state->uapi.event) { - drm_WARN_ON(&dev_priv->drm, - drm_crtc_vblank_get(&crtc->base) != 0); - - spin_lock(&crtc->base.dev->event_lock); - drm_crtc_arm_vblank_event(&crtc->base, - new_crtc_state->uapi.event); - spin_unlock(&crtc->base.dev->event_lock); + } else { + intel_crtc_arm_vblank_event(new_crtc_state); + } - new_crtc_state->uapi.event = NULL; + if (state->base.legacy_cursor_update) { + struct intel_plane *plane; + struct intel_plane_state *old_plane_state; + int i; + + for_each_old_intel_plane_in_state(state, plane, old_plane_state, i) { + if (old_plane_state->uapi.crtc == &crtc->base && + old_plane_state->unpin_work.vblank) { + drm_vblank_work_schedule(&old_plane_state->unpin_work, + drm_crtc_accurate_vblank_count(&crtc->base) + 1, + false); + + /* Remove plane from atomic state, cleanup/free is done from vblank worker. */ + memset(&state->base.planes[i], 0, sizeof(state->base.planes[i])); + } + } } /* |