]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/gpu/drm/i915/intel_display.c
drm/i915: add the BXT and CNL DPLL registers to pipe_config_compare
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / i915 / intel_display.c
index 00cd17c76fdcc3bc5427f53bf45e416d66400655..45d6e57fbe891b235959ef78f601777e02c55570 100644 (file)
@@ -2219,8 +2219,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
                 * something and try to run the system in a "less than optimal"
                 * mode that matches the user configuration.
                 */
-               if (i915_vma_get_fence(vma) == 0)
-                       i915_vma_pin_fence(vma);
+               i915_vma_pin_fence(vma);
        }
 
        i915_vma_get(vma);
@@ -3701,7 +3700,7 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv)
 
 
        /* reset doesn't touch the display */
-       if (!i915.force_reset_modeset_test &&
+       if (!i915_modparams.force_reset_modeset_test &&
            !gpu_reset_clobbers_display(dev_priv))
                return;
 
@@ -3757,7 +3756,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
        int ret;
 
        /* reset doesn't touch the display */
-       if (!i915.force_reset_modeset_test &&
+       if (!i915_modparams.force_reset_modeset_test &&
            !gpu_reset_clobbers_display(dev_priv))
                return;
 
@@ -3770,8 +3769,8 @@ void intel_finish_reset(struct drm_i915_private *dev_priv)
        if (!gpu_reset_clobbers_display(dev_priv)) {
                /* for testing only restore the display */
                ret = __intel_display_resume(dev, state, ctx);
-                       if (ret)
-                               DRM_ERROR("Restoring old state failed with %i\n", ret);
+               if (ret)
+                       DRM_ERROR("Restoring old state failed with %i\n", ret);
        } else {
                /*
                 * The display has been reset as well,
@@ -3804,15 +3803,14 @@ unlock:
        clear_bit(I915_RESET_MODESET, &dev_priv->gpu_error.flags);
 }
 
-static void intel_update_pipe_config(struct intel_crtc *crtc,
-                                    struct intel_crtc_state *old_crtc_state)
+static void intel_update_pipe_config(const struct intel_crtc_state *old_crtc_state,
+                                    const struct intel_crtc_state *new_crtc_state)
 {
+       struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       struct intel_crtc_state *pipe_config =
-               to_intel_crtc_state(crtc->base.state);
 
        /* drm_atomic_helper_update_legacy_modeset_state might not be called. */
-       crtc->base.mode = crtc->base.state->mode;
+       crtc->base.mode = new_crtc_state->base.mode;
 
        /*
         * Update pipe size and adjust fitter if needed: the reason for this is
@@ -3824,17 +3822,17 @@ static void intel_update_pipe_config(struct intel_crtc *crtc,
         */
 
        I915_WRITE(PIPESRC(crtc->pipe),
-                  ((pipe_config->pipe_src_w - 1) << 16) |
-                  (pipe_config->pipe_src_h - 1));
+                  ((new_crtc_state->pipe_src_w - 1) << 16) |
+                  (new_crtc_state->pipe_src_h - 1));
 
        /* on skylake this is done by detaching scalers */
        if (INTEL_GEN(dev_priv) >= 9) {
                skl_detach_scalers(crtc);
 
-               if (pipe_config->pch_pfit.enabled)
+               if (new_crtc_state->pch_pfit.enabled)
                        skylake_pfit_enable(crtc);
        } else if (HAS_PCH_SPLIT(dev_priv)) {
-               if (pipe_config->pch_pfit.enabled)
+               if (new_crtc_state->pch_pfit.enabled)
                        ironlake_pfit_enable(crtc);
                else if (old_crtc_state->pch_pfit.enabled)
                        ironlake_pfit_disable(crtc, true);
@@ -4957,7 +4955,8 @@ void hsw_enable_ips(struct intel_crtc *crtc)
        assert_plane_enabled(dev_priv, crtc->plane);
        if (IS_BROADWELL(dev_priv)) {
                mutex_lock(&dev_priv->rps.hw_lock);
-               WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0xc0000000));
+               WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL,
+                                               IPS_ENABLE | IPS_PCODE_CONTROL));
                mutex_unlock(&dev_priv->rps.hw_lock);
                /* Quoting Art Runyan: "its not safe to expect any particular
                 * value in IPS_CTL bit 31 after enabling IPS through the
@@ -5118,7 +5117,8 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
        struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
        struct drm_atomic_state *old_state = old_crtc_state->base.state;
        struct intel_crtc_state *pipe_config =
-               to_intel_crtc_state(crtc->base.state);
+               intel_atomic_get_new_crtc_state(to_intel_atomic_state(old_state),
+                                               crtc);
        struct drm_plane *primary = crtc->base.primary;
        struct drm_plane_state *old_pri_state =
                drm_atomic_get_existing_plane_state(old_state, primary);
@@ -5130,7 +5130,8 @@ static void intel_post_plane_update(struct intel_crtc_state *old_crtc_state)
 
        if (old_pri_state) {
                struct intel_plane_state *primary_state =
-                       to_intel_plane_state(primary->state);
+                       intel_atomic_get_new_plane_state(to_intel_atomic_state(old_state),
+                                                        to_intel_plane(primary));
                struct intel_plane_state *old_primary_state =
                        to_intel_plane_state(old_pri_state);
 
@@ -5159,7 +5160,8 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state,
 
        if (old_pri_state) {
                struct intel_plane_state *primary_state =
-                       to_intel_plane_state(primary->state);
+                       intel_atomic_get_new_plane_state(old_intel_state,
+                                                        to_intel_plane(primary));
                struct intel_plane_state *old_primary_state =
                        to_intel_plane_state(old_pri_state);
 
@@ -5456,6 +5458,20 @@ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
        return HAS_IPS(to_i915(crtc->base.dev)) && crtc->pipe == PIPE_A;
 }
 
+static void glk_pipe_scaler_clock_gating_wa(struct drm_i915_private *dev_priv,
+                                           enum pipe pipe, bool apply)
+{
+       u32 val = I915_READ(CLKGATE_DIS_PSL(pipe));
+       u32 mask = DPF_GATING_DIS | DPF_RAM_GATING_DIS | DPFR_GATING_DIS;
+
+       if (apply)
+               val |= mask;
+       else
+               val &= ~mask;
+
+       I915_WRITE(CLKGATE_DIS_PSL(pipe), val);
+}
+
 static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
                                struct drm_atomic_state *old_state)
 {
@@ -5466,13 +5482,11 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
        enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
        struct intel_atomic_state *old_intel_state =
                to_intel_atomic_state(old_state);
+       bool psl_clkgate_wa;
 
        if (WARN_ON(intel_crtc->active))
                return;
 
-       if (intel_crtc->config->has_pch_encoder)
-               intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
-
        intel_encoders_pre_pll_enable(crtc, pipe_config, old_state);
 
        if (intel_crtc->config->shared_dpll)
@@ -5506,19 +5520,17 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
 
        intel_crtc->active = true;
 
-       if (intel_crtc->config->has_pch_encoder)
-               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
-       else
-               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
-
        intel_encoders_pre_enable(crtc, pipe_config, old_state);
 
-       if (intel_crtc->config->has_pch_encoder)
-               dev_priv->display.fdi_link_train(intel_crtc, pipe_config);
-
        if (!transcoder_is_dsi(cpu_transcoder))
                intel_ddi_enable_pipe_clock(pipe_config);
 
+       /* Display WA #1180: WaDisableScalarClockGating: glk, cnl */
+       psl_clkgate_wa = (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
+                        intel_crtc->config->pch_pfit.enabled;
+       if (psl_clkgate_wa)
+               glk_pipe_scaler_clock_gating_wa(dev_priv, pipe, true);
+
        if (INTEL_GEN(dev_priv) >= 9)
                skylake_pfit_enable(intel_crtc);
        else
@@ -5552,11 +5564,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
 
        intel_encoders_enable(crtc, pipe_config, old_state);
 
-       if (intel_crtc->config->has_pch_encoder) {
+       if (psl_clkgate_wa) {
                intel_wait_for_vblank(dev_priv, pipe);
-               intel_wait_for_vblank(dev_priv, pipe);
-               intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
-               intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
+               glk_pipe_scaler_clock_gating_wa(dev_priv, pipe, false);
        }
 
        /* If we change the relative order between pipe/planes enabling, we need
@@ -5652,9 +5662,6 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
 
-       if (intel_crtc->config->has_pch_encoder)
-               intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false);
-
        intel_encoders_disable(crtc, old_crtc_state, old_state);
 
        drm_crtc_vblank_off(crtc);
@@ -5679,9 +5686,6 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
                intel_ddi_disable_pipe_clock(intel_crtc->config);
 
        intel_encoders_post_disable(crtc, old_crtc_state, old_state);
-
-       if (old_crtc_state->has_pch_encoder)
-               intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 }
 
 static void i9xx_pfit_enable(struct intel_crtc *crtc)
@@ -6038,7 +6042,7 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
        intel_crtc->enabled_power_domains = 0;
 
        dev_priv->active_crtcs &= ~(1 << intel_crtc->pipe);
-       dev_priv->min_pixclk[intel_crtc->pipe] = 0;
+       dev_priv->min_cdclk[intel_crtc->pipe] = 0;
 }
 
 /*
@@ -6283,6 +6287,9 @@ retry:
 static bool pipe_config_supports_ips(struct drm_i915_private *dev_priv,
                                     struct intel_crtc_state *pipe_config)
 {
+       if (pipe_config->ips_force_disable)
+               return false;
+
        if (pipe_config->pipe_bpp > 24)
                return false;
 
@@ -6307,7 +6314,7 @@ static void hsw_compute_ips_config(struct intel_crtc *crtc,
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
 
-       pipe_config->ips_enabled = i915.enable_ips &&
+       pipe_config->ips_enabled = i915_modparams.enable_ips &&
                hsw_crtc_supports_ips(crtc) &&
                pipe_config_supports_ips(dev_priv, pipe_config);
 }
@@ -6488,8 +6495,8 @@ intel_link_compute_m_n(int bits_per_pixel, int nlanes,
 
 static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
 {
-       if (i915.panel_use_ssc >= 0)
-               return i915.panel_use_ssc != 0;
+       if (i915_modparams.panel_use_ssc >= 0)
+               return i915_modparams.panel_use_ssc != 0;
        return dev_priv->vbt.lvds_use_ssc
                && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
@@ -9039,7 +9046,7 @@ static void cannonlake_get_ddi_pll(struct drm_i915_private *dev_priv,
        u32 temp;
 
        temp = I915_READ(DPCLKA_CFGCR0) & DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
-       id = temp >> (port * 2);
+       id = temp >> DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(port);
 
        if (WARN_ON(id < SKL_DPLL0 || id > SKL_DPLL2))
                return;
@@ -9304,11 +9311,11 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        pipe_config->gamma_mode =
                I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK;
 
-       if (IS_BROADWELL(dev_priv) || dev_priv->info.gen >= 9) {
+       if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) {
                u32 tmp = I915_READ(PIPEMISC(crtc->pipe));
                bool clrspace_yuv = tmp & PIPEMISC_OUTPUT_COLORSPACE_YUV;
 
-               if (IS_GEMINILAKE(dev_priv) || dev_priv->info.gen >= 10) {
+               if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) >= 10) {
                        bool blend_mode_420 = tmp &
                                              PIPEMISC_YUV420_MODE_FULL_BLEND;
 
@@ -9753,7 +9760,7 @@ static void i9xx_disable_cursor(struct intel_plane *plane,
 
 
 /* VESA 640x480x72Hz mode to set on the pipe */
-static struct drm_display_mode load_detect_mode = {
+static const struct drm_display_mode load_detect_mode = {
        DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
                 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
 };
@@ -9788,7 +9795,7 @@ intel_framebuffer_pitch_for_width(int width, int bpp)
 }
 
 static u32
-intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp)
+intel_framebuffer_size_for_mode(const struct drm_display_mode *mode, int bpp)
 {
        u32 pitch = intel_framebuffer_pitch_for_width(mode->hdisplay, bpp);
        return PAGE_ALIGN(pitch * mode->vdisplay);
@@ -9796,7 +9803,7 @@ intel_framebuffer_size_for_mode(struct drm_display_mode *mode, int bpp)
 
 static struct drm_framebuffer *
 intel_framebuffer_create_for_mode(struct drm_device *dev,
-                                 struct drm_display_mode *mode,
+                                 const struct drm_display_mode *mode,
                                  int depth, int bpp)
 {
        struct drm_framebuffer *fb;
@@ -9823,7 +9830,7 @@ intel_framebuffer_create_for_mode(struct drm_device *dev,
 
 static struct drm_framebuffer *
 mode_fits_in_fbdev(struct drm_device *dev,
-                  struct drm_display_mode *mode)
+                  const struct drm_display_mode *mode)
 {
 #ifdef CONFIG_DRM_FBDEV_EMULATION
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -9856,7 +9863,7 @@ mode_fits_in_fbdev(struct drm_device *dev,
 
 static int intel_modeset_setup_plane_state(struct drm_atomic_state *state,
                                           struct drm_crtc *crtc,
-                                          struct drm_display_mode *mode,
+                                          const struct drm_display_mode *mode,
                                           struct drm_framebuffer *fb,
                                           int x, int y)
 {
@@ -9890,7 +9897,7 @@ static int intel_modeset_setup_plane_state(struct drm_atomic_state *state,
 }
 
 int intel_get_load_detect_pipe(struct drm_connector *connector,
-                              struct drm_display_mode *mode,
+                              const struct drm_display_mode *mode,
                               struct intel_load_detect_pipe *old,
                               struct drm_modeset_acquire_ctx *ctx)
 {
@@ -10218,7 +10225,7 @@ int intel_dotclock_calculate(int link_freq,
        if (!m_n->link_n)
                return 0;
 
-       return div_u64((u64)m_n->link_m * link_freq, m_n->link_n);
+       return div_u64(mul_u32_u32(m_n->link_m, link_freq), m_n->link_n);
 }
 
 static void ironlake_pch_clock_get(struct intel_crtc *crtc,
@@ -10245,13 +10252,8 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
        struct drm_display_mode *mode;
        struct intel_crtc_state *pipe_config;
-       int htot = I915_READ(HTOTAL(cpu_transcoder));
-       int hsync = I915_READ(HSYNC(cpu_transcoder));
-       int vtot = I915_READ(VTOTAL(cpu_transcoder));
-       int vsync = I915_READ(VSYNC(cpu_transcoder));
        enum pipe pipe = intel_crtc->pipe;
 
        mode = kzalloc(sizeof(*mode), GFP_KERNEL);
@@ -10278,17 +10280,12 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
        pipe_config->dpll_hw_state.fp1 = I915_READ(FP1(pipe));
        i9xx_crtc_clock_get(intel_crtc, pipe_config);
 
-       mode->clock = pipe_config->port_clock / pipe_config->pixel_multiplier;
-       mode->hdisplay = (htot & 0xffff) + 1;
-       mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
-       mode->hsync_start = (hsync & 0xffff) + 1;
-       mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
-       mode->vdisplay = (vtot & 0xffff) + 1;
-       mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
-       mode->vsync_start = (vsync & 0xffff) + 1;
-       mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
+       pipe_config->base.adjusted_mode.crtc_clock =
+               pipe_config->port_clock / pipe_config->pixel_multiplier;
+
+       intel_get_pipe_timings(intel_crtc, pipe_config);
 
-       drm_mode_set_name(mode);
+       intel_mode_from_pipe_config(mode, pipe_config);
 
        kfree(pipe_config);
 
@@ -10337,7 +10334,7 @@ static bool intel_wm_need_update(struct drm_plane *plane,
        return false;
 }
 
-static bool needs_scaling(struct intel_plane_state *state)
+static bool needs_scaling(const struct intel_plane_state *state)
 {
        int src_w = drm_rect_width(&state->base.src) >> 16;
        int src_h = drm_rect_height(&state->base.src) >> 16;
@@ -10347,7 +10344,9 @@ static bool needs_scaling(struct intel_plane_state *state)
        return (src_w != dst_w || src_h != dst_h);
 }
 
-int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
+int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_state,
+                                   struct drm_crtc_state *crtc_state,
+                                   const struct intel_plane_state *old_plane_state,
                                    struct drm_plane_state *plane_state)
 {
        struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state);
@@ -10356,10 +10355,8 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
        struct intel_plane *plane = to_intel_plane(plane_state->plane);
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_plane_state *old_plane_state =
-               to_intel_plane_state(plane->base.state);
        bool mode_changed = needs_modeset(crtc_state);
-       bool was_crtc_enabled = crtc->state->active;
+       bool was_crtc_enabled = old_crtc_state->base.active;
        bool is_crtc_enabled = crtc_state->active;
        bool turn_off, turn_on, visible, was_visible;
        struct drm_framebuffer *fb = plane_state->fb;
@@ -10850,7 +10847,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
        struct intel_dpll_hw_state dpll_hw_state;
        struct intel_shared_dpll *shared_dpll;
        struct intel_crtc_wm_state wm_state;
-       bool force_thru;
+       bool force_thru, ips_force_disable;
 
        /* FIXME: before the switch to atomic started, a new pipe_config was
         * kzalloc'd. Code that depends on any field being zero should be
@@ -10861,6 +10858,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
        shared_dpll = crtc_state->shared_dpll;
        dpll_hw_state = crtc_state->dpll_hw_state;
        force_thru = crtc_state->pch_pfit.force_thru;
+       ips_force_disable = crtc_state->ips_force_disable;
        if (IS_G4X(dev_priv) ||
            IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                wm_state = crtc_state->wm;
@@ -10874,6 +10872,7 @@ clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
        crtc_state->shared_dpll = shared_dpll;
        crtc_state->dpll_hw_state = dpll_hw_state;
        crtc_state->pch_pfit.force_thru = force_thru;
+       crtc_state->ips_force_disable = ips_force_disable;
        if (IS_G4X(dev_priv) ||
            IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                crtc_state->wm = wm_state;
@@ -11328,6 +11327,18 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
        PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1);
        PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1);
        PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2);
+       PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr0);
+       PIPE_CONF_CHECK_X(dpll_hw_state.ebb0);
+       PIPE_CONF_CHECK_X(dpll_hw_state.ebb4);
+       PIPE_CONF_CHECK_X(dpll_hw_state.pll0);
+       PIPE_CONF_CHECK_X(dpll_hw_state.pll1);
+       PIPE_CONF_CHECK_X(dpll_hw_state.pll2);
+       PIPE_CONF_CHECK_X(dpll_hw_state.pll3);
+       PIPE_CONF_CHECK_X(dpll_hw_state.pll6);
+       PIPE_CONF_CHECK_X(dpll_hw_state.pll8);
+       PIPE_CONF_CHECK_X(dpll_hw_state.pll9);
+       PIPE_CONF_CHECK_X(dpll_hw_state.pll10);
+       PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12);
 
        PIPE_CONF_CHECK_X(dsi_pll.ctrl);
        PIPE_CONF_CHECK_X(dsi_pll.div);
@@ -12076,7 +12087,7 @@ static int intel_atomic_check(struct drm_device *dev,
                        return ret;
                }
 
-               if (i915.fastboot &&
+               if (i915_modparams.fastboot &&
                    intel_pipe_config_compare(dev_priv,
                                        to_intel_crtc_state(old_crtc_state),
                                        pipe_config, true)) {
@@ -12129,73 +12140,10 @@ u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
        return dev->driver->get_vblank_counter(dev, crtc->pipe);
 }
 
-static void intel_atomic_wait_for_vblanks(struct drm_device *dev,
-                                         struct drm_i915_private *dev_priv,
-                                         unsigned crtc_mask)
-{
-       unsigned last_vblank_count[I915_MAX_PIPES];
-       enum pipe pipe;
-       int ret;
-
-       if (!crtc_mask)
-               return;
-
-       for_each_pipe(dev_priv, pipe) {
-               struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
-                                                                 pipe);
-
-               if (!((1 << pipe) & crtc_mask))
-                       continue;
-
-               ret = drm_crtc_vblank_get(&crtc->base);
-               if (WARN_ON(ret != 0)) {
-                       crtc_mask &= ~(1 << pipe);
-                       continue;
-               }
-
-               last_vblank_count[pipe] = drm_crtc_vblank_count(&crtc->base);
-       }
-
-       for_each_pipe(dev_priv, pipe) {
-               struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
-                                                                 pipe);
-               long lret;
-
-               if (!((1 << pipe) & crtc_mask))
-                       continue;
-
-               lret = wait_event_timeout(dev->vblank[pipe].queue,
-                               last_vblank_count[pipe] !=
-                                       drm_crtc_vblank_count(&crtc->base),
-                               msecs_to_jiffies(50));
-
-               WARN(!lret, "pipe %c vblank wait timed out\n", pipe_name(pipe));
-
-               drm_crtc_vblank_put(&crtc->base);
-       }
-}
-
-static bool needs_vblank_wait(struct intel_crtc_state *crtc_state)
-{
-       /* fb updated, need to unpin old fb */
-       if (crtc_state->fb_changed)
-               return true;
-
-       /* wm changes, need vblank before final wm's */
-       if (crtc_state->update_wm_post)
-               return true;
-
-       if (crtc_state->wm.need_postvbl_update)
-               return true;
-
-       return false;
-}
-
 static void intel_update_crtc(struct drm_crtc *crtc,
                              struct drm_atomic_state *state,
                              struct drm_crtc_state *old_crtc_state,
-                             struct drm_crtc_state *new_crtc_state,
-                             unsigned int *crtc_vblank_mask)
+                             struct drm_crtc_state *new_crtc_state)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -12218,13 +12166,9 @@ static void intel_update_crtc(struct drm_crtc *crtc,
        }
 
        drm_atomic_helper_commit_planes_on_crtc(old_crtc_state);
-
-       if (needs_vblank_wait(pipe_config))
-               *crtc_vblank_mask |= drm_crtc_mask(crtc);
 }
 
-static void intel_update_crtcs(struct drm_atomic_state *state,
-                              unsigned int *crtc_vblank_mask)
+static void intel_update_crtcs(struct drm_atomic_state *state)
 {
        struct drm_crtc *crtc;
        struct drm_crtc_state *old_crtc_state, *new_crtc_state;
@@ -12235,12 +12179,11 @@ static void intel_update_crtcs(struct drm_atomic_state *state,
                        continue;
 
                intel_update_crtc(crtc, state, old_crtc_state,
-                                 new_crtc_state, crtc_vblank_mask);
+                                 new_crtc_state);
        }
 }
 
-static void skl_update_crtcs(struct drm_atomic_state *state,
-                            unsigned int *crtc_vblank_mask)
+static void skl_update_crtcs(struct drm_atomic_state *state)
 {
        struct drm_i915_private *dev_priv = to_i915(state->dev);
        struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
@@ -12274,7 +12217,7 @@ static void skl_update_crtcs(struct drm_atomic_state *state,
                        unsigned int cmask = drm_crtc_mask(crtc);
 
                        intel_crtc = to_intel_crtc(crtc);
-                       cstate = to_intel_crtc_state(crtc->state);
+                       cstate = to_intel_crtc_state(new_crtc_state);
                        pipe = intel_crtc->pipe;
 
                        if (updated & cmask || !cstate->base.active)
@@ -12299,7 +12242,7 @@ static void skl_update_crtcs(struct drm_atomic_state *state,
                                vbl_wait = true;
 
                        intel_update_crtc(crtc, state, old_crtc_state,
-                                         new_crtc_state, crtc_vblank_mask);
+                                         new_crtc_state);
 
                        if (vbl_wait)
                                intel_wait_for_vblank(dev_priv, pipe);
@@ -12359,9 +12302,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
        struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        struct drm_crtc *crtc;
        struct intel_crtc_state *intel_cstate;
-       bool hw_check = intel_state->modeset;
        u64 put_domains[I915_MAX_PIPES] = {};
-       unsigned crtc_vblank_mask = 0;
        int i;
 
        intel_atomic_commit_fence_wait(intel_state);
@@ -12376,7 +12317,6 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 
                if (needs_modeset(new_crtc_state) ||
                    to_intel_crtc_state(new_crtc_state)->update_pipe) {
-                       hw_check = true;
 
                        put_domains[to_intel_crtc(crtc)->pipe] =
                                modeset_get_crtc_power_domains(crtc,
@@ -12403,7 +12343,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
                        intel_check_cpu_fifo_underruns(dev_priv);
                        intel_check_pch_fifo_underruns(dev_priv);
 
-                       if (!crtc->state->active) {
+                       if (!new_crtc_state->active) {
                                /*
                                 * Make sure we don't call initial_watermarks
                                 * for ILK-style watermark updates.
@@ -12412,7 +12352,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
                                 */
                                if (INTEL_GEN(dev_priv) >= 9)
                                        dev_priv->display.initial_watermarks(intel_state,
-                                                                            to_intel_crtc_state(crtc->state));
+                                                                            to_intel_crtc_state(new_crtc_state));
                        }
                }
        }
@@ -12451,7 +12391,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
        }
 
        /* Now enable the clocks, plane, pipe, and connectors that we set up. */
-       dev_priv->display.update_crtcs(state, &crtc_vblank_mask);
+       dev_priv->display.update_crtcs(state);
 
        /* FIXME: We should call drm_atomic_helper_commit_hw_done() here
         * already, but still need the state for the delayed optimization. To
@@ -12462,8 +12402,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
         * - switch over to the vblank wait helper in the core after that since
         *   we don't need out special handling any more.
         */
-       if (!state->legacy_cursor_update)
-               intel_atomic_wait_for_vblanks(dev, dev_priv, crtc_vblank_mask);
+       drm_atomic_helper_wait_for_flip_done(dev, state);
 
        /*
         * Now that the vblank has passed, we can go ahead and program the
@@ -12579,21 +12518,10 @@ static int intel_atomic_commit(struct drm_device *dev,
        struct drm_i915_private *dev_priv = to_i915(dev);
        int ret = 0;
 
-       ret = drm_atomic_helper_setup_commit(state, nonblock);
-       if (ret)
-               return ret;
-
        drm_atomic_state_get(state);
        i915_sw_fence_init(&intel_state->commit_ready,
                           intel_atomic_commit_ready);
 
-       ret = intel_atomic_prepare_commit(dev, state);
-       if (ret) {
-               DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret);
-               i915_sw_fence_commit(&intel_state->commit_ready);
-               return ret;
-       }
-
        /*
         * The intel_legacy_cursor_update() fast path takes care
         * of avoiding the vblank waits for simple cursor
@@ -12602,19 +12530,37 @@ static int intel_atomic_commit(struct drm_device *dev,
         * updates happen during the correct frames. Gen9+ have
         * double buffered watermarks and so shouldn't need this.
         *
-        * Do this after drm_atomic_helper_setup_commit() and
-        * intel_atomic_prepare_commit() because we still want
-        * to skip the flip and fb cleanup waits. Although that
-        * does risk yanking the mapping from under the display
-        * engine.
+        * Unset state->legacy_cursor_update before the call to
+        * drm_atomic_helper_setup_commit() because otherwise
+        * drm_atomic_helper_wait_for_flip_done() is a noop and
+        * we get FIFO underruns because we didn't wait
+        * for vblank.
         *
         * FIXME doing watermarks and fb cleanup from a vblank worker
         * (assuming we had any) would solve these problems.
         */
-       if (INTEL_GEN(dev_priv) < 9)
-               state->legacy_cursor_update = false;
+       if (INTEL_GEN(dev_priv) < 9 && state->legacy_cursor_update) {
+               struct intel_crtc_state *new_crtc_state;
+               struct intel_crtc *crtc;
+               int i;
+
+               for_each_new_intel_crtc_in_state(intel_state, crtc, new_crtc_state, i)
+                       if (new_crtc_state->wm.need_postvbl_update ||
+                           new_crtc_state->update_wm_post)
+                               state->legacy_cursor_update = false;
+       }
+
+       ret = intel_atomic_prepare_commit(dev, state);
+       if (ret) {
+               DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret);
+               i915_sw_fence_commit(&intel_state->commit_ready);
+               return ret;
+       }
+
+       ret = drm_atomic_helper_setup_commit(state, nonblock);
+       if (!ret)
+               ret = drm_atomic_helper_swap_state(state, true);
 
-       ret = drm_atomic_helper_swap_state(state, true);
        if (ret) {
                i915_sw_fence_commit(&intel_state->commit_ready);
 
@@ -12626,8 +12572,8 @@ static int intel_atomic_commit(struct drm_device *dev,
        intel_atomic_track_fbs(state);
 
        if (intel_state->modeset) {
-               memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
-                      sizeof(intel_state->min_pixclk));
+               memcpy(dev_priv->min_cdclk, intel_state->min_cdclk,
+                      sizeof(intel_state->min_cdclk));
                dev_priv->active_crtcs = intel_state->active_crtcs;
                dev_priv->cdclk.logical = intel_state->cdclk.logical;
                dev_priv->cdclk.actual = intel_state->cdclk.actual;
@@ -12656,6 +12602,58 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
        .set_crc_source = intel_crtc_set_crc_source,
 };
 
+struct wait_rps_boost {
+       struct wait_queue_entry wait;
+
+       struct drm_crtc *crtc;
+       struct drm_i915_gem_request *request;
+};
+
+static int do_rps_boost(struct wait_queue_entry *_wait,
+                       unsigned mode, int sync, void *key)
+{
+       struct wait_rps_boost *wait = container_of(_wait, typeof(*wait), wait);
+       struct drm_i915_gem_request *rq = wait->request;
+
+       gen6_rps_boost(rq, NULL);
+       i915_gem_request_put(rq);
+
+       drm_crtc_vblank_put(wait->crtc);
+
+       list_del(&wait->wait.entry);
+       kfree(wait);
+       return 1;
+}
+
+static void add_rps_boost_after_vblank(struct drm_crtc *crtc,
+                                      struct dma_fence *fence)
+{
+       struct wait_rps_boost *wait;
+
+       if (!dma_fence_is_i915(fence))
+               return;
+
+       if (INTEL_GEN(to_i915(crtc->dev)) < 6)
+               return;
+
+       if (drm_crtc_vblank_get(crtc))
+               return;
+
+       wait = kmalloc(sizeof(*wait), GFP_KERNEL);
+       if (!wait) {
+               drm_crtc_vblank_put(crtc);
+               return;
+       }
+
+       wait->request = to_request(dma_fence_get(fence));
+       wait->crtc = crtc;
+
+       wait->wait.func = do_rps_boost;
+       wait->wait.flags = 0;
+
+       add_wait_queue(drm_crtc_vblank_waitqueue(crtc), &wait->wait);
+}
+
 /**
  * intel_prepare_plane_fb - Prepare fb for usage on plane
  * @plane: drm plane to prepare for
@@ -12753,12 +12751,22 @@ intel_prepare_plane_fb(struct drm_plane *plane,
                return ret;
 
        if (!new_state->fence) { /* implicit fencing */
+               struct dma_fence *fence;
+
                ret = i915_sw_fence_await_reservation(&intel_state->commit_ready,
                                                      obj->resv, NULL,
                                                      false, I915_FENCE_TIMEOUT,
                                                      GFP_KERNEL);
                if (ret < 0)
                        return ret;
+
+               fence = reservation_object_get_excl_rcu(obj->resv);
+               if (fence) {
+                       add_rps_boost_after_vblank(new_state->crtc, fence);
+                       dma_fence_put(fence);
+               }
+       } else {
+               add_rps_boost_after_vblank(new_state->crtc, new_state->fence);
        }
 
        return 0;
@@ -12875,29 +12883,29 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc,
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_crtc_state *intel_cstate =
-               to_intel_crtc_state(crtc->state);
        struct intel_crtc_state *old_intel_cstate =
                to_intel_crtc_state(old_crtc_state);
        struct intel_atomic_state *old_intel_state =
                to_intel_atomic_state(old_crtc_state->state);
-       bool modeset = needs_modeset(crtc->state);
+       struct intel_crtc_state *intel_cstate =
+               intel_atomic_get_new_crtc_state(old_intel_state, intel_crtc);
+       bool modeset = needs_modeset(&intel_cstate->base);
 
        if (!modeset &&
            (intel_cstate->base.color_mgmt_changed ||
             intel_cstate->update_pipe)) {
-               intel_color_set_csc(crtc->state);
-               intel_color_load_luts(crtc->state);
+               intel_color_set_csc(&intel_cstate->base);
+               intel_color_load_luts(&intel_cstate->base);
        }
 
        /* Perform vblank evasion around commit operation */
-       intel_pipe_update_start(intel_crtc);
+       intel_pipe_update_start(intel_cstate);
 
        if (modeset)
                goto out;
 
        if (intel_cstate->update_pipe)
-               intel_update_pipe_config(intel_crtc, old_intel_cstate);
+               intel_update_pipe_config(old_intel_cstate, intel_cstate);
        else if (INTEL_GEN(dev_priv) >= 9)
                skl_detach_scalers(intel_crtc);
 
@@ -12911,8 +12919,12 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc,
                                     struct drm_crtc_state *old_crtc_state)
 {
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_atomic_state *old_intel_state =
+               to_intel_atomic_state(old_crtc_state->state);
+       struct intel_crtc_state *new_crtc_state =
+               intel_atomic_get_new_crtc_state(old_intel_state, intel_crtc);
 
-       intel_pipe_update_end(intel_crtc);
+       intel_pipe_update_end(new_crtc_state);
 }
 
 /**
@@ -13061,6 +13073,14 @@ intel_legacy_cursor_update(struct drm_plane *plane,
                goto slow;
 
        old_plane_state = plane->state;
+       /*
+        * Don't do an async update if there is an outstanding commit modifying
+        * the plane.  This prevents our async update's changes from getting
+        * overridden by a previous synchronous update's state.
+        */
+       if (old_plane_state->commit &&
+           !try_wait_for_completion(&old_plane_state->commit->hw_done))
+               goto slow;
 
        /*
         * If any parameters change that may affect watermarks,
@@ -13091,6 +13111,8 @@ intel_legacy_cursor_update(struct drm_plane *plane,
        new_plane_state->crtc_h = crtc_h;
 
        ret = intel_plane_atomic_check_with_state(to_intel_crtc_state(crtc->state),
+                                                 to_intel_crtc_state(crtc->state), /* FIXME need a new crtc state? */
+                                                 to_intel_plane_state(plane->state),
                                                  to_intel_plane_state(new_plane_state));
        if (ret)
                goto out_free;
@@ -13120,17 +13142,12 @@ intel_legacy_cursor_update(struct drm_plane *plane,
        }
 
        old_fb = old_plane_state->fb;
-       old_vma = to_intel_plane_state(old_plane_state)->vma;
 
        i915_gem_track_fb(intel_fb_obj(old_fb), intel_fb_obj(fb),
                          intel_plane->frontbuffer_bit);
 
        /* Swap plane state */
-       new_plane_state->fence = old_plane_state->fence;
-       *to_intel_plane_state(old_plane_state) = *to_intel_plane_state(new_plane_state);
-       new_plane_state->fence = NULL;
-       new_plane_state->fb = old_fb;
-       to_intel_plane_state(new_plane_state)->vma = NULL;
+       plane->state = new_plane_state;
 
        if (plane->state->visible) {
                trace_intel_update_plane(plane, to_intel_crtc(crtc));
@@ -13142,13 +13159,17 @@ intel_legacy_cursor_update(struct drm_plane *plane,
                intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc));
        }
 
+       old_vma = fetch_and_zero(&to_intel_plane_state(old_plane_state)->vma);
        if (old_vma)
                intel_unpin_fb_vma(old_vma);
 
 out_unlock:
        mutex_unlock(&dev_priv->drm.struct_mutex);
 out_free:
-       intel_plane_destroy_state(plane, new_plane_state);
+       if (ret)
+               intel_plane_destroy_state(plane, new_plane_state);
+       else
+               intel_plane_destroy_state(plane, old_plane_state);
        return ret;
 
 slow:
@@ -13663,7 +13684,7 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
 
        } else if (HAS_PCH_SPLIT(dev_priv)) {
                int found;
-               dpd_is_edp = intel_dp_is_edp(dev_priv, PORT_D);
+               dpd_is_edp = intel_dp_is_port_edp(dev_priv, PORT_D);
 
                if (has_edp_a(dev_priv))
                        intel_dp_init(dev_priv, DP_A, PORT_A);
@@ -13706,14 +13727,14 @@ static void intel_setup_outputs(struct drm_i915_private *dev_priv)
                 * trust the port type the VBT declares as we've seen at least
                 * HDMI ports that the VBT claim are DP or eDP.
                 */
-               has_edp = intel_dp_is_edp(dev_priv, PORT_B);
+               has_edp = intel_dp_is_port_edp(dev_priv, PORT_B);
                has_port = intel_bios_is_port_present(dev_priv, PORT_B);
                if (I915_READ(VLV_DP_B) & DP_DETECTED || has_port)
                        has_edp &= intel_dp_init(dev_priv, VLV_DP_B, PORT_B);
                if ((I915_READ(VLV_HDMIB) & SDVO_DETECTED || has_port) && !has_edp)
                        intel_hdmi_init(dev_priv, VLV_HDMIB, PORT_B);
 
-               has_edp = intel_dp_is_edp(dev_priv, PORT_C);
+               has_edp = intel_dp_is_port_edp(dev_priv, PORT_C);
                has_port = intel_bios_is_port_present(dev_priv, PORT_C);
                if (I915_READ(VLV_DP_C) & DP_DETECTED || has_port)
                        has_edp &= intel_dp_init(dev_priv, VLV_DP_C, PORT_C);
@@ -14206,7 +14227,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
                dev_priv->display.fdi_link_train = hsw_fdi_link_train;
        }
 
-       if (dev_priv->info.gen >= 9)
+       if (INTEL_GEN(dev_priv) >= 9)
                dev_priv->display.update_crtcs = skl_update_crtcs;
        else
                dev_priv->display.update_crtcs = intel_update_crtcs;
@@ -15030,7 +15051,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
        for_each_intel_crtc(dev, crtc) {
                struct intel_crtc_state *crtc_state =
                        to_intel_crtc_state(crtc->base.state);
-               int pixclk = 0;
+               int min_cdclk = 0;
 
                memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
                if (crtc_state->base.active) {
@@ -15051,22 +15072,18 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 
                        intel_crtc_compute_pixel_rate(crtc_state);
 
-                       if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv) ||
-                           IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-                               pixclk = crtc_state->pixel_rate;
-                       else
-                               WARN_ON(dev_priv->display.modeset_calc_cdclk);
-
-                       /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
-                       if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
-                               pixclk = DIV_ROUND_UP(pixclk * 100, 95);
+                       if (dev_priv->display.modeset_calc_cdclk) {
+                               min_cdclk = intel_crtc_compute_min_cdclk(crtc_state);
+                               if (WARN_ON(min_cdclk < 0))
+                                       min_cdclk = 0;
+                       }
 
                        drm_calc_timestamping_constants(&crtc->base,
                                                        &crtc_state->base.adjusted_mode);
                        update_scanline_offset(crtc);
                }
 
-               dev_priv->min_pixclk[crtc->pipe] = pixclk;
+               dev_priv->min_cdclk[crtc->pipe] = min_cdclk;
 
                intel_pipe_config_sanity_check(dev_priv, crtc_state);
        }
@@ -15184,6 +15201,7 @@ void intel_display_resume(struct drm_device *dev)
        if (!ret)
                ret = __intel_display_resume(dev, state, &ctx);
 
+       intel_enable_ipc(dev_priv);
        drm_modeset_drop_locks(&ctx);
        drm_modeset_acquire_fini(&ctx);