diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_vblank.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_vblank.c | 356 |
1 files changed, 202 insertions, 154 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_vblank.c b/drivers/gpu/drm/i915/display/intel_vblank.c index baf7354cb6e2..139fa5deba80 100644 --- a/drivers/gpu/drm/i915/display/intel_vblank.c +++ b/drivers/gpu/drm/i915/display/intel_vblank.c @@ -3,8 +3,11 @@ * Copyright © 2022-2023 Intel Corporation */ +#include <drm/drm_vblank.h> + #include "i915_drv.h" #include "i915_reg.h" +#include "intel_color.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_display_types.h" @@ -66,8 +69,8 @@ */ u32 i915_get_vblank_counter(struct drm_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->dev); - struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; + struct intel_display *display = to_intel_display(crtc->dev); + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); const struct drm_display_mode *mode = &vblank->hwmode; enum pipe pipe = to_intel_crtc(crtc)->pipe; u32 pixel, vbl_start, hsync_start, htotal; @@ -89,9 +92,7 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc) htotal = mode->crtc_htotal; hsync_start = mode->crtc_hsync_start; - vbl_start = mode->crtc_vblank_start; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - vbl_start = DIV_ROUND_UP(vbl_start, 2); + vbl_start = intel_mode_vblank_start(mode); /* Convert to pixel count */ vbl_start *= htotal; @@ -104,7 +105,8 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc) * we get a low value that's stable across two reads of the high * register. */ - frame = intel_de_read64_2x32(dev_priv, PIPEFRAMEPIXEL(pipe), PIPEFRAME(pipe)); + frame = intel_de_read64_2x32(display, PIPEFRAMEPIXEL(display, pipe), + PIPEFRAME(display, pipe)); pixel = frame & PIPE_PIXEL_MASK; frame = (frame >> PIPE_FRAME_LOW_SHIFT) & 0xffffff; @@ -119,21 +121,20 @@ u32 i915_get_vblank_counter(struct drm_crtc *crtc) u32 g4x_get_vblank_counter(struct drm_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->dev); - struct drm_vblank_crtc *vblank = &dev_priv->drm.vblank[drm_crtc_index(crtc)]; + struct intel_display *display = to_intel_display(crtc->dev); + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); enum pipe pipe = to_intel_crtc(crtc)->pipe; if (!vblank->max_vblank_count) return 0; - return intel_de_read(dev_priv, PIPE_FRMCOUNT_G4X(pipe)); + return intel_de_read(display, PIPE_FRMCOUNT_G4X(display, pipe)); } static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct drm_vblank_crtc *vblank = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + struct intel_display *display = to_intel_display(crtc); + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); const struct drm_display_mode *mode = &vblank->hwmode; u32 htotal = mode->crtc_htotal; u32 clock = mode->crtc_clock; @@ -151,16 +152,16 @@ static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) * pipe frame time stamp. The time stamp value * is sampled at every start of vertical blank. */ - scan_prev_time = intel_de_read_fw(dev_priv, + scan_prev_time = intel_de_read_fw(display, PIPE_FRMTMSTMP(crtc->pipe)); /* * The TIMESTAMP_CTR register has the current * time stamp value. */ - scan_curr_time = intel_de_read_fw(dev_priv, IVB_TIMESTAMP_CTR); + scan_curr_time = intel_de_read_fw(display, IVB_TIMESTAMP_CTR); - scan_post_time = intel_de_read_fw(dev_priv, + scan_post_time = intel_de_read_fw(display, PIPE_FRMTMSTMP(crtc->pipe)); } while (scan_post_time != scan_prev_time); @@ -178,8 +179,7 @@ static u32 intel_crtc_scanlines_since_frame_timestamp(struct intel_crtc *crtc) */ static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) { - struct drm_vblank_crtc *vblank = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); const struct drm_display_mode *mode = &vblank->hwmode; u32 vblank_start = mode->crtc_vblank_start; u32 vtotal = mode->crtc_vtotal; @@ -192,33 +192,68 @@ static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) return scanline; } +int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + + /* + * The scanline counter increments at the leading edge of hsync. + * + * On most platforms it starts counting from vtotal-1 on the + * first active line. That means the scanline counter value is + * always one less than what we would expect. Ie. just after + * start of vblank, which also occurs at start of hsync (on the + * last active line), the scanline counter will read vblank_start-1. + * + * On gen2 the scanline counter starts counting from 1 instead + * of vtotal-1, so we have to subtract one. + * + * On HSW+ the behaviour of the scanline counter depends on the output + * type. For DP ports it behaves like most other platforms, but on HDMI + * there's an extra 1 line difference. So we need to add two instead of + * one to the value. + * + * On VLV/CHV DSI the scanline counter would appear to increment + * approx. 1/3 of a scanline before start of vblank. Unfortunately + * that means we can't tell whether we're in vblank or not while + * we're on that particular line. We must still set scanline_offset + * to 1 so that the vblank timestamps come out correct when we query + * the scanline counter from within the vblank interrupt handler. + * However if queried just before the start of vblank we'll get an + * answer that's slightly in the future. + */ + if (DISPLAY_VER(display) >= 20 || display->platform.battlemage) + return 1; + else if (DISPLAY_VER(display) >= 9 || + display->platform.broadwell || display->platform.haswell) + return intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) ? 2 : 1; + else if (DISPLAY_VER(display) >= 3) + return 1; + else + return -1; +} + /* * intel_de_read_fw(), only for fast reads of display block, no need for * forcewake etc. */ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - const struct drm_display_mode *mode; - struct drm_vblank_crtc *vblank; + struct intel_display *display = to_intel_display(crtc); + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); + const struct drm_display_mode *mode = &vblank->hwmode; enum pipe pipe = crtc->pipe; int position, vtotal; if (!crtc->active) return 0; - vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - mode = &vblank->hwmode; - if (crtc->mode_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) return __intel_get_crtc_scanline_from_timestamp(crtc); - vtotal = mode->crtc_vtotal; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - vtotal /= 2; + vtotal = intel_mode_vtotal(mode); - position = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; + position = intel_de_read_fw(display, PIPEDSL(display, pipe)) & PIPEDSL_LINE_MASK; /* * On HSW, the DSL reg (0x70000) appears to return 0 if we @@ -232,12 +267,13 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) * problem. We may need to extend this to include other platforms, * but so far testing only shows the problem on HSW. */ - if (HAS_DDI(dev_priv) && !position) { + if (HAS_DDI(display) && !position) { int i, temp; for (i = 0; i < 100; i++) { udelay(1); - temp = intel_de_read_fw(dev_priv, PIPEDSL(pipe)) & PIPEDSL_LINE_MASK; + temp = intel_de_read_fw(display, + PIPEDSL(display, pipe)) & PIPEDSL_LINE_MASK; if (temp != position) { position = temp; break; @@ -249,21 +285,7 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) * See update_scanline_offset() for the details on the * scanline_offset adjustment. */ - return (position + crtc->scanline_offset) % vtotal; -} - -int intel_crtc_scanline_to_hw(struct intel_crtc *crtc, int scanline) -{ - const struct drm_vblank_crtc *vblank = - &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; - const struct drm_display_mode *mode = &vblank->hwmode; - int vtotal; - - vtotal = mode->crtc_vtotal; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - vtotal /= 2; - - return (scanline + vtotal - crtc->scanline_offset) % vtotal; + return (position + vtotal + crtc->scanline_offset) % vtotal; } /* @@ -276,21 +298,29 @@ int intel_crtc_scanline_to_hw(struct intel_crtc *crtc, int scanline) * all register accesses to the same cacheline to be serialized, * otherwise they may hang. */ -static void intel_vblank_section_enter(struct drm_i915_private *i915) +#ifdef I915 +static void intel_vblank_section_enter(struct intel_display *display) __acquires(i915->uncore.lock) { -#ifdef I915 + struct drm_i915_private *i915 = to_i915(display->drm); spin_lock(&i915->uncore.lock); -#endif } -static void intel_vblank_section_exit(struct drm_i915_private *i915) +static void intel_vblank_section_exit(struct intel_display *display) __releases(i915->uncore.lock) { -#ifdef I915 + struct drm_i915_private *i915 = to_i915(display->drm); spin_unlock(&i915->uncore.lock); -#endif } +#else +static void intel_vblank_section_enter(struct intel_display *display) +{ +} + +static void intel_vblank_section_exit(struct intel_display *display) +{ +} +#endif static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, bool in_vblank_irq, @@ -298,19 +328,18 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, ktime_t *stime, ktime_t *etime, const struct drm_display_mode *mode) { - struct drm_device *dev = _crtc->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_display *display = to_intel_display(_crtc->dev); struct intel_crtc *crtc = to_intel_crtc(_crtc); enum pipe pipe = crtc->pipe; int position; int vbl_start, vbl_end, hsync_start, htotal, vtotal; unsigned long irqflags; - bool use_scanline_counter = DISPLAY_VER(dev_priv) >= 5 || - IS_G4X(dev_priv) || DISPLAY_VER(dev_priv) == 2 || + bool use_scanline_counter = DISPLAY_VER(display) >= 5 || + display->platform.g4x || DISPLAY_VER(display) == 2 || crtc->mode_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; - if (drm_WARN_ON(&dev_priv->drm, !mode->crtc_clock)) { - drm_dbg(&dev_priv->drm, + if (drm_WARN_ON(display->drm, !mode->crtc_clock)) { + drm_dbg(display->drm, "trying to get scanoutpos for disabled pipe %c\n", pipe_name(pipe)); return false; @@ -318,15 +347,9 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, htotal = mode->crtc_htotal; hsync_start = mode->crtc_hsync_start; - vtotal = mode->crtc_vtotal; - vbl_start = mode->crtc_vblank_start; - vbl_end = mode->crtc_vblank_end; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - vbl_start = DIV_ROUND_UP(vbl_start, 2); - vbl_end /= 2; - vtotal /= 2; - } + vtotal = intel_mode_vtotal(mode); + vbl_start = intel_mode_vblank_start(mode); + vbl_end = intel_mode_vblank_end(mode); /* * Enter vblank critical section, as we will do multiple @@ -334,7 +357,7 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, * preemption disabled, so the following code must not block. */ local_irq_save(irqflags); - intel_vblank_section_enter(dev_priv); + intel_vblank_section_enter(display); /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ @@ -349,7 +372,7 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, /* * Already exiting vblank? If so, shift our position - * so it looks like we're already apporaching the full + * so it looks like we're already approaching the full * vblank end. This should make the generated timestamp * more or less match when the active portion will start. */ @@ -366,7 +389,7 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, * We can split this into vertical and horizontal * scanout position. */ - position = (intel_de_read_fw(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; + position = (intel_de_read_fw(display, PIPEFRAMEPIXEL(display, pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; /* convert to pixel counts */ vbl_start *= htotal; @@ -402,7 +425,7 @@ static bool i915_get_crtc_scanoutpos(struct drm_crtc *_crtc, /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ - intel_vblank_section_exit(dev_priv); + intel_vblank_section_exit(display); local_irq_restore(irqflags); /* @@ -437,42 +460,42 @@ bool intel_crtc_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, int intel_get_crtc_scanline(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_display *display = to_intel_display(crtc); unsigned long irqflags; int position; local_irq_save(irqflags); - intel_vblank_section_enter(dev_priv); + intel_vblank_section_enter(display); position = __intel_get_crtc_scanline(crtc); - intel_vblank_section_exit(dev_priv); + intel_vblank_section_exit(display); local_irq_restore(irqflags); return position; } -static bool pipe_scanline_is_moving(struct drm_i915_private *dev_priv, +static bool pipe_scanline_is_moving(struct intel_display *display, enum pipe pipe) { - i915_reg_t reg = PIPEDSL(pipe); + i915_reg_t reg = PIPEDSL(display, pipe); u32 line1, line2; - line1 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; + line1 = intel_de_read(display, reg) & PIPEDSL_LINE_MASK; msleep(5); - line2 = intel_de_read(dev_priv, reg) & PIPEDSL_LINE_MASK; + line2 = intel_de_read(display, reg) & PIPEDSL_LINE_MASK; return line1 != line2; } static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct intel_display *display = to_intel_display(crtc); enum pipe pipe = crtc->pipe; /* Wait for the display line to settle/start moving */ - if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100)) - drm_err(&dev_priv->drm, + if (wait_for(pipe_scanline_is_moving(display, pipe) == state, 100)) + drm_err(display->drm, "pipe %c scanline %s wait timed out\n", pipe_name(pipe), str_on_off(state)); } @@ -487,75 +510,40 @@ void intel_wait_for_pipe_scanline_moving(struct intel_crtc *crtc) wait_for_pipe_scanline_moving(crtc, true); } -static int intel_crtc_scanline_offset(const struct intel_crtc_state *crtc_state) +static void intel_crtc_active_timings(struct drm_display_mode *mode, + int *vmax_vblank_start, + const struct intel_crtc_state *crtc_state, + bool vrr_enable) { - struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - - /* - * The scanline counter increments at the leading edge of hsync. - * - * On most platforms it starts counting from vtotal-1 on the - * first active line. That means the scanline counter value is - * always one less than what we would expect. Ie. just after - * start of vblank, which also occurs at start of hsync (on the - * last active line), the scanline counter will read vblank_start-1. - * - * On gen2 the scanline counter starts counting from 1 instead - * of vtotal-1, so we have to subtract one (or rather add vtotal-1 - * to keep the value positive), instead of adding one. - * - * On HSW+ the behaviour of the scanline counter depends on the output - * type. For DP ports it behaves like most other platforms, but on HDMI - * there's an extra 1 line difference. So we need to add two instead of - * one to the value. - * - * On VLV/CHV DSI the scanline counter would appear to increment - * approx. 1/3 of a scanline before start of vblank. Unfortunately - * that means we can't tell whether we're in vblank or not while - * we're on that particular line. We must still set scanline_offset - * to 1 so that the vblank timestamps come out correct when we query - * the scanline counter from within the vblank interrupt handler. - * However if queried just before the start of vblank we'll get an - * answer that's slightly in the future. - */ - if (DISPLAY_VER(i915) == 2) { - int vtotal; + drm_mode_init(mode, &crtc_state->hw.adjusted_mode); + *vmax_vblank_start = 0; - vtotal = adjusted_mode->crtc_vtotal; - if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) - vtotal /= 2; + if (!vrr_enable) + return; - return vtotal - 1; - } else if (HAS_DDI(i915) && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { - return 2; - } else { - return 1; - } + mode->crtc_vtotal = intel_vrr_vmax_vtotal(crtc_state); + mode->crtc_vblank_end = intel_vrr_vmax_vtotal(crtc_state); + mode->crtc_vblank_start = intel_vrr_vmin_vblank_start(crtc_state); + *vmax_vblank_start = intel_vrr_vmax_vblank_start(crtc_state); } void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state, bool vrr_enable) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *i915 = to_i915(crtc->base.dev); u8 mode_flags = crtc_state->mode_flags; struct drm_display_mode adjusted_mode; int vmax_vblank_start = 0; unsigned long irqflags; - drm_mode_init(&adjusted_mode, &crtc_state->hw.adjusted_mode); + intel_crtc_active_timings(&adjusted_mode, &vmax_vblank_start, + crtc_state, vrr_enable); - if (vrr_enable) { - drm_WARN_ON(&i915->drm, (mode_flags & I915_MODE_FLAG_VRR) == 0); - - adjusted_mode.crtc_vtotal = crtc_state->vrr.vmax; - adjusted_mode.crtc_vblank_end = crtc_state->vrr.vmax; - adjusted_mode.crtc_vblank_start = intel_vrr_vmin_vblank_start(crtc_state); - vmax_vblank_start = intel_vrr_vmax_vblank_start(crtc_state); - } else { + if (vrr_enable) + drm_WARN_ON(display->drm, (mode_flags & I915_MODE_FLAG_VRR) == 0); + else mode_flags &= ~I915_MODE_FLAG_VRR; - } /* * Belts and suspenders locking to guarantee everyone sees 100% @@ -569,8 +557,8 @@ void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state, * __intel_get_crtc_scanline()) with vblank_time_lock? * Need to audit everything to make sure it's safe. */ - spin_lock_irqsave(&i915->drm.vblank_time_lock, irqflags); - intel_vblank_section_enter(i915); + spin_lock_irqsave(&display->drm->vblank_time_lock, irqflags); + intel_vblank_section_enter(display); drm_calc_timestamping_constants(&crtc->base, &adjusted_mode); @@ -579,11 +567,21 @@ void intel_crtc_update_active_timings(const struct intel_crtc_state *crtc_state, crtc->mode_flags = mode_flags; crtc->scanline_offset = intel_crtc_scanline_offset(crtc_state); - intel_vblank_section_exit(i915); - spin_unlock_irqrestore(&i915->drm.vblank_time_lock, irqflags); + intel_vblank_section_exit(display); + spin_unlock_irqrestore(&display->drm->vblank_time_lock, irqflags); } -static int intel_mode_vblank_start(const struct drm_display_mode *mode) +int intel_mode_vdisplay(const struct drm_display_mode *mode) +{ + int vdisplay = mode->crtc_vdisplay; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vdisplay = DIV_ROUND_UP(vdisplay, 2); + + return vdisplay; +} + +int intel_mode_vblank_start(const struct drm_display_mode *mode) { int vblank_start = mode->crtc_vblank_start; @@ -593,30 +591,75 @@ static int intel_mode_vblank_start(const struct drm_display_mode *mode) return vblank_start; } +int intel_mode_vblank_end(const struct drm_display_mode *mode) +{ + int vblank_end = mode->crtc_vblank_end; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vblank_end /= 2; + + return vblank_end; +} + +int intel_mode_vtotal(const struct drm_display_mode *mode) +{ + int vtotal = mode->crtc_vtotal; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + vtotal /= 2; + + return vtotal; +} + +int intel_mode_vblank_delay(const struct drm_display_mode *mode) +{ + return intel_mode_vblank_start(mode) - intel_mode_vdisplay(mode); +} + +static const struct intel_crtc_state * +pre_commit_crtc_state(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *new_crtc_state) +{ + /* + * During fastsets/etc. the transcoder is still + * running with the old timings at this point. + */ + if (intel_crtc_needs_modeset(new_crtc_state)) + return new_crtc_state; + else + return old_crtc_state; +} + +const struct intel_crtc_state * +intel_pre_commit_crtc_state(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + + return pre_commit_crtc_state(old_crtc_state, new_crtc_state); +} + void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, const struct intel_crtc_state *new_crtc_state, struct intel_vblank_evade_ctx *evade) { + struct intel_display *display = to_intel_display(new_crtc_state); struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); - struct drm_i915_private *i915 = to_i915(crtc->base.dev); const struct intel_crtc_state *crtc_state; const struct drm_display_mode *adjusted_mode; + int vblank_delay; evade->crtc = crtc; - evade->need_vlv_dsi_wa = (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) && + evade->need_vlv_dsi_wa = (display->platform.valleyview || + display->platform.cherryview) && intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI); - /* - * During fastsets/etc. the transcoder is still - * running with the old timings at this point. - * - * TODO: maybe just use the active timings here? - */ - if (intel_crtc_needs_modeset(new_crtc_state)) - crtc_state = new_crtc_state; - else - crtc_state = old_crtc_state; + /* TODO: maybe just use the active timings here? */ + crtc_state = pre_commit_crtc_state(old_crtc_state, new_crtc_state); adjusted_mode = &crtc_state->hw.adjusted_mode; @@ -629,8 +672,12 @@ void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, evade->vblank_start = intel_vrr_vmin_vblank_start(crtc_state); else evade->vblank_start = intel_vrr_vmax_vblank_start(crtc_state); + + vblank_delay = intel_vrr_vblank_delay(crtc_state); } else { evade->vblank_start = intel_mode_vblank_start(adjusted_mode); + + vblank_delay = intel_mode_vblank_delay(adjusted_mode); } /* FIXME needs to be calibrated sensibly */ @@ -646,15 +693,16 @@ void intel_vblank_evade_init(const struct intel_crtc_state *old_crtc_state, * DSB execution waits for the transcoder's undelayed vblank, * hence we must kick off the commit before that. */ - if (new_crtc_state->dsb || new_crtc_state->update_m_n || new_crtc_state->update_lrr) - evade->min -= adjusted_mode->crtc_vblank_start - adjusted_mode->crtc_vdisplay; + if (intel_color_uses_dsb(new_crtc_state) || + new_crtc_state->update_m_n || new_crtc_state->update_lrr) + evade->min -= vblank_delay; } /* must be called with vblank interrupt already enabled! */ int intel_vblank_evade(struct intel_vblank_evade_ctx *evade) { struct intel_crtc *crtc = evade->crtc; - struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_display *display = to_intel_display(crtc); long timeout = msecs_to_jiffies_timeout(1); wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); DEFINE_WAIT(wait); @@ -676,7 +724,7 @@ int intel_vblank_evade(struct intel_vblank_evade_ctx *evade) break; if (!timeout) { - drm_err(&i915->drm, + drm_err(display->drm, "Potential atomic update failure on pipe %c\n", pipe_name(crtc->pipe)); break; |