]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/i915/intel_display.c
drm/i915: Fix cursor updates on some platforms
[karo-tx-linux.git] / drivers / gpu / drm / i915 / intel_display.c
index 9106ea32b048cac4783ae316d7cc198a4bf8ae88..ae4fb72a3394ba7736344e21ddb8b7f281019811 100644 (file)
@@ -1193,9 +1193,8 @@ void assert_pipe(struct drm_i915_private *dev_priv,
                                                                      pipe);
        enum intel_display_power_domain power_domain;
 
-       /* if we need the pipe quirk it must be always on */
-       if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
-           (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
+       /* we keep both pipes enabled on 830 */
+       if (IS_I830(dev_priv))
                state = true;
 
        power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
@@ -1278,7 +1277,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
                I915_STATE_WARN(val & SPRITE_ENABLE,
                     "sprite %c assertion failure, should be off on pipe %c but is still active\n",
                     plane_name(pipe), pipe_name(pipe));
-       } else if (INTEL_GEN(dev_priv) >= 5) {
+       } else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) {
                u32 val = I915_READ(DVSCNTR(pipe));
                I915_STATE_WARN(val & DVS_ENABLE,
                     "sprite %c assertion failure, should be off on pipe %c but is still active\n",
@@ -1550,6 +1549,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        i915_reg_t reg = DPLL(crtc->pipe);
        u32 dpll = crtc->config->dpll_hw_state.dpll;
+       int i;
 
        assert_pipe_disabled(dev_priv, crtc->pipe);
 
@@ -1596,15 +1596,11 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
        }
 
        /* We do this three times for luck */
-       I915_WRITE(reg, dpll);
-       POSTING_READ(reg);
-       udelay(150); /* wait for warmup */
-       I915_WRITE(reg, dpll);
-       POSTING_READ(reg);
-       udelay(150); /* wait for warmup */
-       I915_WRITE(reg, dpll);
-       POSTING_READ(reg);
-       udelay(150); /* wait for warmup */
+       for (i = 0; i < 3; i++) {
+               I915_WRITE(reg, dpll);
+               POSTING_READ(reg);
+               udelay(150); /* wait for warmup */
+       }
 }
 
 /**
@@ -1632,8 +1628,7 @@ static void i9xx_disable_pll(struct intel_crtc *crtc)
        }
 
        /* Don't disable pipe or pipe PLLs if needed */
-       if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
-           (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
+       if (IS_I830(dev_priv))
                return;
 
        /* Make sure the pipe isn't still relying on us */
@@ -1916,8 +1911,8 @@ static void intel_enable_pipe(struct intel_crtc *crtc)
        reg = PIPECONF(cpu_transcoder);
        val = I915_READ(reg);
        if (val & PIPECONF_ENABLE) {
-               WARN_ON(!((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
-                         (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE)));
+               /* we keep both pipes enabled on 830 */
+               WARN_ON(!IS_I830(dev_priv));
                return;
        }
 
@@ -1977,8 +1972,7 @@ static void intel_disable_pipe(struct intel_crtc *crtc)
                val &= ~PIPECONF_DOUBLE_WIDE;
 
        /* Don't disable pipe or pipe PLLs if needed */
-       if (!(pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) &&
-           !(pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
+       if (!IS_I830(dev_priv))
                val &= ~PIPECONF_ENABLE;
 
        I915_WRITE(reg, val);
@@ -2085,6 +2079,18 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
        }
 }
 
+static unsigned int intel_cursor_alignment(const struct drm_i915_private *dev_priv)
+{
+       if (IS_I830(dev_priv))
+               return 16 * 1024;
+       else if (IS_I85X(dev_priv))
+               return 256;
+       else if (IS_I845G(dev_priv) || IS_I865G(dev_priv))
+               return 32;
+       else
+               return 4 * 1024;
+}
+
 static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_priv)
 {
        if (INTEL_INFO(dev_priv)->gen >= 9)
@@ -2387,11 +2393,17 @@ u32 intel_compute_tile_offset(int *x, int *y,
                              const struct intel_plane_state *state,
                              int plane)
 {
-       const struct drm_i915_private *dev_priv = to_i915(state->base.plane->dev);
+       struct intel_plane *intel_plane = to_intel_plane(state->base.plane);
+       struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
        const struct drm_framebuffer *fb = state->base.fb;
        unsigned int rotation = state->base.rotation;
        int pitch = intel_fb_pitch(fb, plane, rotation);
-       u32 alignment = intel_surf_alignment(fb, plane);
+       u32 alignment;
+
+       if (intel_plane->id == PLANE_CURSOR)
+               alignment = intel_cursor_alignment(dev_priv);
+       else
+               alignment = intel_surf_alignment(fb, plane);
 
        return _intel_compute_tile_offset(dev_priv, x, y, fb, plane, pitch,
                                          rotation, alignment);
@@ -2469,7 +2481,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
 
                offset = _intel_compute_tile_offset(dev_priv, &x, &y,
                                                    fb, i, fb->pitches[i],
-                                                   DRM_ROTATE_0, tile_size);
+                                                   DRM_MODE_ROTATE_0, tile_size);
                offset /= tile_size;
 
                if (fb->modifier != DRM_FORMAT_MOD_LINEAR) {
@@ -2504,7 +2516,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
                        drm_rect_rotate(&r,
                                        rot_info->plane[i].width * tile_width,
                                        rot_info->plane[i].height * tile_height,
-                                       DRM_ROTATE_270);
+                                       DRM_MODE_ROTATE_270);
                        x = r.x1;
                        y = r.y1;
 
@@ -2751,7 +2763,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
                                false);
        intel_pre_disable_primary_noatomic(&intel_crtc->base);
        trace_intel_disable_plane(primary, intel_crtc);
-       intel_plane->disable_plane(primary, &intel_crtc->base);
+       intel_plane->disable_plane(intel_plane, intel_crtc);
 
        return;
 
@@ -2940,7 +2952,7 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
        if (drm_rotation_90_or_270(rotation))
                drm_rect_rotate(&plane_state->base.src,
                                fb->width << 16, fb->height << 16,
-                               DRM_ROTATE_270);
+                               DRM_MODE_ROTATE_270);
 
        /*
         * Handle the AUX surface first since
@@ -2982,10 +2994,8 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
                dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
 
-       if (INTEL_GEN(dev_priv) < 4) {
-               if (crtc->pipe == PIPE_B)
-                       dspcntr |= DISPPLANE_SEL_PIPE_B;
-       }
+       if (INTEL_GEN(dev_priv) < 4)
+               dspcntr |= DISPPLANE_SEL_PIPE(crtc->pipe);
 
        switch (fb->format->format) {
        case DRM_FORMAT_C8:
@@ -3018,10 +3028,10 @@ static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
            fb->modifier == I915_FORMAT_MOD_X_TILED)
                dspcntr |= DISPPLANE_TILED;
 
-       if (rotation & DRM_ROTATE_180)
+       if (rotation & DRM_MODE_ROTATE_180)
                dspcntr |= DISPPLANE_ROTATE_180;
 
-       if (rotation & DRM_REFLECT_X)
+       if (rotation & DRM_MODE_REFLECT_X)
                dspcntr |= DISPPLANE_MIRROR;
 
        return dspcntr;
@@ -3049,10 +3059,10 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
                int src_w = drm_rect_width(&plane_state->base.src) >> 16;
                int src_h = drm_rect_height(&plane_state->base.src) >> 16;
 
-               if (rotation & DRM_ROTATE_180) {
+               if (rotation & DRM_MODE_ROTATE_180) {
                        src_x += src_w - 1;
                        src_y += src_h - 1;
-               } else if (rotation & DRM_REFLECT_X) {
+               } else if (rotation & DRM_MODE_REFLECT_X) {
                        src_x += src_w - 1;
                }
        }
@@ -3064,14 +3074,14 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
        return 0;
 }
 
-static void i9xx_update_primary_plane(struct drm_plane *primary,
+static void i9xx_update_primary_plane(struct intel_plane *primary,
                                      const struct intel_crtc_state *crtc_state,
                                      const struct intel_plane_state *plane_state)
 {
-       struct drm_i915_private *dev_priv = to_i915(primary->dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
-       struct drm_framebuffer *fb = plane_state->base.fb;
-       int plane = intel_crtc->plane;
+       struct drm_i915_private *dev_priv = to_i915(primary->base.dev);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       enum plane plane = primary->plane;
        u32 linear_offset;
        u32 dspcntr = plane_state->ctl;
        i915_reg_t reg = DSPCNTR(plane);
@@ -3082,12 +3092,12 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 
        if (INTEL_GEN(dev_priv) >= 4)
-               intel_crtc->dspaddr_offset = plane_state->main.offset;
+               crtc->dspaddr_offset = plane_state->main.offset;
        else
-               intel_crtc->dspaddr_offset = linear_offset;
+               crtc->dspaddr_offset = linear_offset;
 
-       intel_crtc->adjusted_x = x;
-       intel_crtc->adjusted_y = y;
+       crtc->adjusted_x = x;
+       crtc->adjusted_y = y;
 
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
@@ -3113,31 +3123,29 @@ static void i9xx_update_primary_plane(struct drm_plane *primary,
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
                I915_WRITE_FW(DSPSURF(plane),
                              intel_plane_ggtt_offset(plane_state) +
-                             intel_crtc->dspaddr_offset);
+                             crtc->dspaddr_offset);
                I915_WRITE_FW(DSPOFFSET(plane), (y << 16) | x);
        } else if (INTEL_GEN(dev_priv) >= 4) {
                I915_WRITE_FW(DSPSURF(plane),
                              intel_plane_ggtt_offset(plane_state) +
-                             intel_crtc->dspaddr_offset);
+                             crtc->dspaddr_offset);
                I915_WRITE_FW(DSPTILEOFF(plane), (y << 16) | x);
                I915_WRITE_FW(DSPLINOFF(plane), linear_offset);
        } else {
                I915_WRITE_FW(DSPADDR(plane),
                              intel_plane_ggtt_offset(plane_state) +
-                             intel_crtc->dspaddr_offset);
+                             crtc->dspaddr_offset);
        }
        POSTING_READ_FW(reg);
 
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
-static void i9xx_disable_primary_plane(struct drm_plane *primary,
-                                      struct drm_crtc *crtc)
+static void i9xx_disable_primary_plane(struct intel_plane *primary,
+                                      struct intel_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);
-       int plane = intel_crtc->plane;
+       struct drm_i915_private *dev_priv = to_i915(primary->base.dev);
+       enum plane plane = primary->plane;
        unsigned long irqflags;
 
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
@@ -3272,17 +3280,17 @@ static u32 skl_plane_ctl_tiling(uint64_t fb_modifier)
 static u32 skl_plane_ctl_rotation(unsigned int rotation)
 {
        switch (rotation) {
-       case DRM_ROTATE_0:
+       case DRM_MODE_ROTATE_0:
                break;
        /*
-        * DRM_ROTATE_ is counter clockwise to stay compatible with Xrandr
+        * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
         * while i915 HW rotation is clockwise, thats why this swapping.
         */
-       case DRM_ROTATE_90:
+       case DRM_MODE_ROTATE_90:
                return PLANE_CTL_ROTATE_270;
-       case DRM_ROTATE_180:
+       case DRM_MODE_ROTATE_180:
                return PLANE_CTL_ROTATE_180;
-       case DRM_ROTATE_270:
+       case DRM_MODE_ROTATE_270:
                return PLANE_CTL_ROTATE_90;
        default:
                MISSING_CASE(rotation);
@@ -3322,16 +3330,15 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state,
        return plane_ctl;
 }
 
-static void skylake_update_primary_plane(struct drm_plane *plane,
+static void skylake_update_primary_plane(struct intel_plane *plane,
                                         const struct intel_crtc_state *crtc_state,
                                         const struct intel_plane_state *plane_state)
 {
-       struct drm_device *dev = plane->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
-       struct drm_framebuffer *fb = plane_state->base.fb;
-       enum plane_id plane_id = to_intel_plane(plane)->id;
-       enum pipe pipe = to_intel_plane(plane)->pipe;
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       enum plane_id plane_id = plane->id;
+       enum pipe pipe = plane->pipe;
        u32 plane_ctl = plane_state->ctl;
        unsigned int rotation = plane_state->base.rotation;
        u32 stride = skl_plane_stride(fb, 0, rotation);
@@ -3353,10 +3360,10 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
        dst_w--;
        dst_h--;
 
-       intel_crtc->dspaddr_offset = surf_addr;
+       crtc->dspaddr_offset = surf_addr;
 
-       intel_crtc->adjusted_x = src_x;
-       intel_crtc->adjusted_y = src_y;
+       crtc->adjusted_x = src_x;
+       crtc->adjusted_y = src_y;
 
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
@@ -3395,13 +3402,12 @@ static void skylake_update_primary_plane(struct drm_plane *plane,
        spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
-static void skylake_disable_primary_plane(struct drm_plane *primary,
-                                         struct drm_crtc *crtc)
+static void skylake_disable_primary_plane(struct intel_plane *primary,
+                                         struct intel_crtc *crtc)
 {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       enum plane_id plane_id = to_intel_plane(primary)->id;
-       enum pipe pipe = to_intel_plane(primary)->pipe;
+       struct drm_i915_private *dev_priv = to_i915(primary->base.dev);
+       enum plane_id plane_id = primary->id;
+       enum pipe pipe = primary->pipe;
        unsigned long irqflags;
 
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
@@ -3434,7 +3440,7 @@ static void intel_update_primary_planes(struct drm_device *dev)
                        trace_intel_update_plane(&plane->base,
                                                 to_intel_crtc(crtc));
 
-                       plane->update_plane(&plane->base,
+                       plane->update_plane(plane,
                                            to_intel_crtc_state(crtc->state),
                                            plane_state);
                }
@@ -4864,12 +4870,9 @@ static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc)
 {
        if (intel_crtc->overlay) {
                struct drm_device *dev = intel_crtc->base.dev;
-               struct drm_i915_private *dev_priv = to_i915(dev);
 
                mutex_lock(&dev->struct_mutex);
-               dev_priv->mm.interruptible = false;
                (void) intel_overlay_switch_off(intel_crtc->overlay);
-               dev_priv->mm.interruptible = true;
                mutex_unlock(&dev->struct_mutex);
        }
 
@@ -5089,7 +5092,7 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask
        intel_crtc_dpms_overlay_disable(intel_crtc);
 
        drm_for_each_plane_mask(p, dev, plane_mask)
-               to_intel_plane(p)->disable_plane(p, crtc);
+               to_intel_plane(p)->disable_plane(to_intel_plane(p), intel_crtc);
 
        /*
         * FIXME: Once we grow proper nuclear flip support out of this we need
@@ -5725,6 +5728,8 @@ static void i9xx_set_pll_dividers(struct intel_crtc *crtc)
 static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
                             struct drm_atomic_state *old_state)
 {
+       struct intel_atomic_state *old_intel_state =
+               to_intel_atomic_state(old_state);
        struct drm_crtc *crtc = pipe_config->base.crtc;
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -5757,7 +5762,11 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config,
 
        intel_color_load_luts(&pipe_config->base);
 
-       intel_update_watermarks(intel_crtc);
+       if (dev_priv->display.initial_watermarks != NULL)
+               dev_priv->display.initial_watermarks(old_intel_state,
+                                                    intel_crtc->config);
+       else
+               intel_update_watermarks(intel_crtc);
        intel_enable_pipe(intel_crtc);
 
        assert_vblank_disabled(crtc);
@@ -5824,6 +5833,10 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state,
 
        if (!dev_priv->display.initial_watermarks)
                intel_update_watermarks(intel_crtc);
+
+       /* clock the pipe down to 640x480@60 to potentially save power */
+       if (IS_I830(dev_priv))
+               i830_enable_pipe(dev_priv, pipe);
 }
 
 static void intel_crtc_disable_noatomic(struct drm_crtc *crtc,
@@ -5924,9 +5937,10 @@ void intel_encoder_destroy(struct drm_encoder *encoder)
 
 /* Cross check the actual hw state with our own modeset state tracking (and it's
  * internal consistency). */
-static void intel_connector_verify_state(struct intel_connector *connector)
+static void intel_connector_verify_state(struct drm_crtc_state *crtc_state,
+                                        struct drm_connector_state *conn_state)
 {
-       struct drm_crtc *crtc = connector->base.state->crtc;
+       struct intel_connector *connector = to_intel_connector(conn_state->connector);
 
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
                      connector->base.base.id,
@@ -5934,15 +5948,14 @@ static void intel_connector_verify_state(struct intel_connector *connector)
 
        if (connector->get_hw_state(connector)) {
                struct intel_encoder *encoder = connector->encoder;
-               struct drm_connector_state *conn_state = connector->base.state;
 
-               I915_STATE_WARN(!crtc,
+               I915_STATE_WARN(!crtc_state,
                         "connector enabled without attached crtc\n");
 
-               if (!crtc)
+               if (!crtc_state)
                        return;
 
-               I915_STATE_WARN(!crtc->state->active,
+               I915_STATE_WARN(!crtc_state->active,
                      "connector is active, but attached crtc isn't\n");
 
                if (!encoder || encoder->type == INTEL_OUTPUT_DP_MST)
@@ -5954,20 +5967,30 @@ static void intel_connector_verify_state(struct intel_connector *connector)
                I915_STATE_WARN(conn_state->crtc != encoder->base.crtc,
                        "attached encoder crtc differs from connector crtc\n");
        } else {
-               I915_STATE_WARN(crtc && crtc->state->active,
+               I915_STATE_WARN(crtc_state && crtc_state->active,
                        "attached crtc is active, but connector isn't\n");
-               I915_STATE_WARN(!crtc && connector->base.state->best_encoder,
+               I915_STATE_WARN(!crtc_state && conn_state->best_encoder,
                        "best encoder set without crtc!\n");
        }
 }
 
 int intel_connector_init(struct intel_connector *connector)
 {
-       drm_atomic_helper_connector_reset(&connector->base);
+       struct intel_digital_connector_state *conn_state;
 
-       if (!connector->base.state)
+       /*
+        * Allocate enough memory to hold intel_digital_connector_state,
+        * This might be a few bytes too many, but for connectors that don't
+        * need it we'll free the state and allocate a smaller one on the first
+        * succesful commit anyway.
+        */
+       conn_state = kzalloc(sizeof(*conn_state), GFP_KERNEL);
+       if (!conn_state)
                return -ENOMEM;
 
+       __drm_atomic_helper_connector_reset(&connector->base,
+                                           &conn_state->base);
+
        return 0;
 }
 
@@ -6382,8 +6405,8 @@ static void vlv_pllb_recal_opamp(struct drm_i915_private *dev_priv, enum pipe
        vlv_dpio_write(dev_priv, pipe, VLV_PLL_DW9(1), reg_val);
 
        reg_val = vlv_dpio_read(dev_priv, pipe, VLV_REF_DW13);
-       reg_val &= 0x8cffffff;
-       reg_val = 0x8c000000;
+       reg_val &= 0x00ffffff;
+       reg_val |= 0x8c000000;
        vlv_dpio_write(dev_priv, pipe, VLV_REF_DW13, reg_val);
 
        reg_val = vlv_dpio_read(dev_priv, pipe, VLV_PLL_DW9(1));
@@ -7025,8 +7048,8 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
 
        pipeconf = 0;
 
-       if ((intel_crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
-           (intel_crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
+       /* we keep both pipes enabled on 830 */
+       if (IS_I830(dev_priv))
                pipeconf |= I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE;
 
        if (intel_crtc->config->double_wide)
@@ -8187,9 +8210,6 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
-       struct dpll reduced_clock;
-       bool has_reduced_clock = false;
-       struct intel_shared_dpll *pll;
        const struct intel_limit *limit;
        int refclk = 120000;
 
@@ -8231,20 +8251,14 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
                return -EINVAL;
        }
 
-       ironlake_compute_dpll(crtc, crtc_state,
-                             has_reduced_clock ? &reduced_clock : NULL);
+       ironlake_compute_dpll(crtc, crtc_state, NULL);
 
-       pll = intel_get_shared_dpll(crtc, crtc_state, NULL);
-       if (pll == NULL) {
+       if (!intel_get_shared_dpll(crtc, crtc_state, NULL)) {
                DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
                                 pipe_name(crtc->pipe));
                return -EINVAL;
        }
 
-       if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
-           has_reduced_clock)
-               crtc->lowfreq_avail = true;
-
        return 0;
 }
 
@@ -8860,6 +8874,22 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
        return 0;
 }
 
+static void cannonlake_get_ddi_pll(struct drm_i915_private *dev_priv,
+                                  enum port port,
+                                  struct intel_crtc_state *pipe_config)
+{
+       enum intel_dpll_id id;
+       u32 temp;
+
+       temp = I915_READ(DPCLKA_CFGCR0) & DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
+       id = temp >> (port * 2);
+
+       if (WARN_ON(id < SKL_DPLL0 || id > SKL_DPLL2))
+               return;
+
+       pipe_config->shared_dpll = intel_get_shared_dpll_by_id(dev_priv, id);
+}
+
 static void bxt_get_ddi_pll(struct drm_i915_private *dev_priv,
                                enum port port,
                                struct intel_crtc_state *pipe_config)
@@ -9047,7 +9077,9 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
 
        port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
 
-       if (IS_GEN9_BC(dev_priv))
+       if (IS_CANNONLAKE(dev_priv))
+               cannonlake_get_ddi_pll(dev_priv, port, pipe_config);
+       else if (IS_GEN9_BC(dev_priv))
                skylake_get_ddi_pll(dev_priv, port, pipe_config);
        else if (IS_GEN9_LP(dev_priv))
                bxt_get_ddi_pll(dev_priv, port, pipe_config);
@@ -9148,38 +9180,171 @@ out:
        return active;
 }
 
+static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
+{
+       struct drm_i915_private *dev_priv =
+               to_i915(plane_state->base.plane->dev);
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+       u32 base;
+
+       if (INTEL_INFO(dev_priv)->cursor_needs_physical)
+               base = obj->phys_handle->busaddr;
+       else
+               base = intel_plane_ggtt_offset(plane_state);
+
+       base += plane_state->main.offset;
+
+       /* ILK+ do this automagically */
+       if (HAS_GMCH_DISPLAY(dev_priv) &&
+           plane_state->base.rotation & DRM_MODE_ROTATE_180)
+               base += (plane_state->base.crtc_h *
+                        plane_state->base.crtc_w - 1) * fb->format->cpp[0];
+
+       return base;
+}
+
+static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
+{
+       int x = plane_state->base.crtc_x;
+       int y = plane_state->base.crtc_y;
+       u32 pos = 0;
+
+       if (x < 0) {
+               pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
+               x = -x;
+       }
+       pos |= x << CURSOR_X_SHIFT;
+
+       if (y < 0) {
+               pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
+               y = -y;
+       }
+       pos |= y << CURSOR_Y_SHIFT;
+
+       return pos;
+}
+
+static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
+{
+       const struct drm_mode_config *config =
+               &plane_state->base.plane->dev->mode_config;
+       int width = plane_state->base.crtc_w;
+       int height = plane_state->base.crtc_h;
+
+       return width > 0 && width <= config->cursor_width &&
+               height > 0 && height <= config->cursor_height;
+}
+
+static int intel_check_cursor(struct intel_crtc_state *crtc_state,
+                             struct intel_plane_state *plane_state)
+{
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       int src_x, src_y;
+       u32 offset;
+       int ret;
+
+       ret = drm_plane_helper_check_state(&plane_state->base,
+                                          &plane_state->clip,
+                                          DRM_PLANE_HELPER_NO_SCALING,
+                                          DRM_PLANE_HELPER_NO_SCALING,
+                                          true, true);
+       if (ret)
+               return ret;
+
+       if (!fb)
+               return 0;
+
+       if (fb->modifier != DRM_FORMAT_MOD_LINEAR) {
+               DRM_DEBUG_KMS("cursor cannot be tiled\n");
+               return -EINVAL;
+       }
+
+       src_x = plane_state->base.src_x >> 16;
+       src_y = plane_state->base.src_y >> 16;
+
+       intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
+       offset = intel_compute_tile_offset(&src_x, &src_y, plane_state, 0);
+
+       if (src_x != 0 || src_y != 0) {
+               DRM_DEBUG_KMS("Arbitrary cursor panning not supported\n");
+               return -EINVAL;
+       }
+
+       plane_state->main.offset = offset;
+
+       return 0;
+}
+
 static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
                           const struct intel_plane_state *plane_state)
 {
-       unsigned int width = plane_state->base.crtc_w;
-       unsigned int stride = roundup_pow_of_two(width) * 4;
+       const struct drm_framebuffer *fb = plane_state->base.fb;
 
-       switch (stride) {
-       default:
-               WARN_ONCE(1, "Invalid cursor width/stride, width=%u, stride=%u\n",
-                         width, stride);
-               stride = 256;
-               /* fallthrough */
+       return CURSOR_ENABLE |
+               CURSOR_GAMMA_ENABLE |
+               CURSOR_FORMAT_ARGB |
+               CURSOR_STRIDE(fb->pitches[0]);
+}
+
+static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
+{
+       int width = plane_state->base.crtc_w;
+
+       /*
+        * 845g/865g are only limited by the width of their cursors,
+        * the height is arbitrary up to the precision of the register.
+        */
+       return intel_cursor_size_ok(plane_state) && IS_ALIGNED(width, 64);
+}
+
+static int i845_check_cursor(struct intel_plane *plane,
+                            struct intel_crtc_state *crtc_state,
+                            struct intel_plane_state *plane_state)
+{
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       int ret;
+
+       ret = intel_check_cursor(crtc_state, plane_state);
+       if (ret)
+               return ret;
+
+       /* if we want to turn off the cursor ignore width and height */
+       if (!fb)
+               return 0;
+
+       /* Check for which cursor types we support */
+       if (!i845_cursor_size_ok(plane_state)) {
+               DRM_DEBUG("Cursor dimension %dx%d not supported\n",
+                         plane_state->base.crtc_w,
+                         plane_state->base.crtc_h);
+               return -EINVAL;
+       }
+
+       switch (fb->pitches[0]) {
        case 256:
        case 512:
        case 1024:
        case 2048:
                break;
+       default:
+               DRM_DEBUG_KMS("Invalid cursor stride (%u)\n",
+                             fb->pitches[0]);
+               return -EINVAL;
        }
 
-       return CURSOR_ENABLE |
-               CURSOR_GAMMA_ENABLE |
-               CURSOR_FORMAT_ARGB |
-               CURSOR_STRIDE(stride);
+       plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
+
+       return 0;
 }
 
-static void i845_update_cursor(struct drm_crtc *crtc, u32 base,
+static void i845_update_cursor(struct intel_plane *plane,
+                              const struct intel_crtc_state *crtc_state,
                               const struct intel_plane_state *plane_state)
 {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       uint32_t cntl = 0, size = 0;
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       u32 cntl = 0, base = 0, pos = 0, size = 0;
+       unsigned long irqflags;
 
        if (plane_state && plane_state->base.visible) {
                unsigned int width = plane_state->base.crtc_w;
@@ -9187,35 +9352,41 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base,
 
                cntl = plane_state->ctl;
                size = (height << 12) | width;
-       }
 
-       if (intel_crtc->cursor_cntl != 0 &&
-           (intel_crtc->cursor_base != base ||
-            intel_crtc->cursor_size != size ||
-            intel_crtc->cursor_cntl != cntl)) {
-               /* On these chipsets we can only modify the base/size/stride
-                * whilst the cursor is disabled.
-                */
-               I915_WRITE_FW(CURCNTR(PIPE_A), 0);
-               POSTING_READ_FW(CURCNTR(PIPE_A));
-               intel_crtc->cursor_cntl = 0;
+               base = intel_cursor_base(plane_state);
+               pos = intel_cursor_position(plane_state);
        }
 
-       if (intel_crtc->cursor_base != base) {
-               I915_WRITE_FW(CURBASE(PIPE_A), base);
-               intel_crtc->cursor_base = base;
-       }
+       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
-       if (intel_crtc->cursor_size != size) {
+       /* On these chipsets we can only modify the base/size/stride
+        * whilst the cursor is disabled.
+        */
+       if (plane->cursor.base != base ||
+           plane->cursor.size != size ||
+           plane->cursor.cntl != cntl) {
+               I915_WRITE_FW(CURCNTR(PIPE_A), 0);
+               I915_WRITE_FW(CURBASE(PIPE_A), base);
                I915_WRITE_FW(CURSIZE, size);
-               intel_crtc->cursor_size = size;
-       }
-
-       if (intel_crtc->cursor_cntl != cntl) {
+               I915_WRITE_FW(CURPOS(PIPE_A), pos);
                I915_WRITE_FW(CURCNTR(PIPE_A), cntl);
-               POSTING_READ_FW(CURCNTR(PIPE_A));
-               intel_crtc->cursor_cntl = cntl;
+
+               plane->cursor.base = base;
+               plane->cursor.size = size;
+               plane->cursor.cntl = cntl;
+       } else {
+               I915_WRITE_FW(CURPOS(PIPE_A), pos);
        }
+
+       POSTING_READ_FW(CURCNTR(PIPE_A));
+
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+}
+
+static void i845_disable_cursor(struct intel_plane *plane,
+                               struct intel_crtc *crtc)
+{
+       i845_update_cursor(plane, NULL, NULL);
 }
 
 static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
@@ -9224,7 +9395,6 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
        struct drm_i915_private *dev_priv =
                to_i915(plane_state->base.plane->dev);
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
-       enum pipe pipe = crtc->pipe;
        u32 cntl;
 
        cntl = MCURSOR_GAMMA_ENABLE;
@@ -9232,7 +9402,7 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
        if (HAS_DDI(dev_priv))
                cntl |= CURSOR_PIPE_CSC_ENABLE;
 
-       cntl |= pipe << 28; /* Connect to correct pipe */
+       cntl |= MCURSOR_PIPE_SELECT(crtc->pipe);
 
        switch (plane_state->base.crtc_w) {
        case 64:
@@ -9249,122 +9419,170 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
                return 0;
        }
 
-       if (plane_state->base.rotation & DRM_ROTATE_180)
+       if (plane_state->base.rotation & DRM_MODE_ROTATE_180)
                cntl |= CURSOR_ROTATE_180;
 
        return cntl;
 }
 
-static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base,
-                              const struct intel_plane_state *plane_state)
+static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
 {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       uint32_t cntl = 0;
+       struct drm_i915_private *dev_priv =
+               to_i915(plane_state->base.plane->dev);
+       int width = plane_state->base.crtc_w;
+       int height = plane_state->base.crtc_h;
 
-       if (plane_state && plane_state->base.visible)
-               cntl = plane_state->ctl;
+       if (!intel_cursor_size_ok(plane_state))
+               return false;
 
-       if (intel_crtc->cursor_cntl != cntl) {
-               I915_WRITE_FW(CURCNTR(pipe), cntl);
-               POSTING_READ_FW(CURCNTR(pipe));
-               intel_crtc->cursor_cntl = cntl;
+       /* Cursor width is limited to a few power-of-two sizes */
+       switch (width) {
+       case 256:
+       case 128:
+       case 64:
+               break;
+       default:
+               return false;
        }
 
-       /* and commit changes on next vblank */
-       I915_WRITE_FW(CURBASE(pipe), base);
-       POSTING_READ_FW(CURBASE(pipe));
+       /*
+        * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
+        * height from 8 lines up to the cursor width, when the
+        * cursor is not rotated. Everything else requires square
+        * cursors.
+        */
+       if (HAS_CUR_FBC(dev_priv) &&
+           plane_state->base.rotation & DRM_MODE_ROTATE_0) {
+               if (height < 8 || height > width)
+                       return false;
+       } else {
+               if (height != width)
+                       return false;
+       }
 
-       intel_crtc->cursor_base = base;
+       return true;
 }
 
-/* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
-static void intel_crtc_update_cursor(struct drm_crtc *crtc,
-                                    const struct intel_plane_state *plane_state)
+static int i9xx_check_cursor(struct intel_plane *plane,
+                            struct intel_crtc_state *crtc_state,
+                            struct intel_plane_state *plane_state)
 {
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       int pipe = intel_crtc->pipe;
-       u32 base = intel_crtc->cursor_addr;
-       unsigned long irqflags;
-       u32 pos = 0;
-
-       if (plane_state) {
-               int x = plane_state->base.crtc_x;
-               int y = plane_state->base.crtc_y;
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       enum pipe pipe = plane->pipe;
+       int ret;
 
-               if (x < 0) {
-                       pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
-                       x = -x;
-               }
-               pos |= x << CURSOR_X_SHIFT;
+       ret = intel_check_cursor(crtc_state, plane_state);
+       if (ret)
+               return ret;
 
-               if (y < 0) {
-                       pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
-                       y = -y;
-               }
-               pos |= y << CURSOR_Y_SHIFT;
+       /* if we want to turn off the cursor ignore width and height */
+       if (!fb)
+               return 0;
 
-               /* ILK+ do this automagically */
-               if (HAS_GMCH_DISPLAY(dev_priv) &&
-                   plane_state->base.rotation & DRM_ROTATE_180) {
-                       base += (plane_state->base.crtc_h *
-                                plane_state->base.crtc_w - 1) * 4;
-               }
+       /* Check for which cursor types we support */
+       if (!i9xx_cursor_size_ok(plane_state)) {
+               DRM_DEBUG("Cursor dimension %dx%d not supported\n",
+                         plane_state->base.crtc_w,
+                         plane_state->base.crtc_h);
+               return -EINVAL;
        }
 
-       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+       if (fb->pitches[0] != plane_state->base.crtc_w * fb->format->cpp[0]) {
+               DRM_DEBUG_KMS("Invalid cursor stride (%u) (cursor width %d)\n",
+                             fb->pitches[0], plane_state->base.crtc_w);
+               return -EINVAL;
+       }
 
-       I915_WRITE_FW(CURPOS(pipe), pos);
+       /*
+        * There's something wrong with the cursor on CHV pipe C.
+        * If it straddles the left edge of the screen then
+        * moving it away from the edge or disabling it often
+        * results in a pipe underrun, and often that can lead to
+        * dead pipe (constant underrun reported, and it scans
+        * out just a solid color). To recover from that, the
+        * display power well must be turned off and on again.
+        * Refuse the put the cursor into that compromised position.
+        */
+       if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
+           plane_state->base.visible && plane_state->base.crtc_x < 0) {
+               DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n");
+               return -EINVAL;
+       }
 
-       if (IS_I845G(dev_priv) || IS_I865G(dev_priv))
-               i845_update_cursor(crtc, base, plane_state);
-       else
-               i9xx_update_cursor(crtc, base, plane_state);
+       plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
 
-       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
+       return 0;
 }
 
-static bool cursor_size_ok(struct drm_i915_private *dev_priv,
-                          uint32_t width, uint32_t height)
+static void i9xx_update_cursor(struct intel_plane *plane,
+                              const struct intel_crtc_state *crtc_state,
+                              const struct intel_plane_state *plane_state)
 {
-       if (width == 0 || height == 0)
-               return false;
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum pipe pipe = plane->pipe;
+       u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0;
+       unsigned long irqflags;
 
-       /*
-        * 845g/865g are special in that they are only limited by
-        * the width of their cursors, the height is arbitrary up to
-        * the precision of the register. Everything else requires
-        * square cursors, limited to a few power-of-two sizes.
-        */
-       if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
-               if ((width & 63) != 0)
-                       return false;
+       if (plane_state && plane_state->base.visible) {
+               cntl = plane_state->ctl;
 
-               if (width > (IS_I845G(dev_priv) ? 64 : 512))
-                       return false;
+               if (plane_state->base.crtc_h != plane_state->base.crtc_w)
+                       fbc_ctl = CUR_FBC_CTL_EN | (plane_state->base.crtc_h - 1);
 
-               if (height > 1023)
-                       return false;
+               base = intel_cursor_base(plane_state);
+               pos = intel_cursor_position(plane_state);
+       }
+
+       spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
+
+       /*
+        * On some platforms writing CURCNTR first will also
+        * cause CURPOS to be armed by the CURBASE write.
+        * Without the CURCNTR write the CURPOS write would
+        * arm itself. Thus we always start the full update
+        * with a CURCNTR write.
+        *
+        * On other platforms CURPOS always requires the
+        * CURBASE write to arm the update. Additonally
+        * a write to any of the cursor register will cancel
+        * an already armed cursor update. Thus leaving out
+        * the CURBASE write after CURPOS could lead to a
+        * cursor that doesn't appear to move, or even change
+        * shape. Thus we always write CURBASE.
+        *
+        * CURCNTR and CUR_FBC_CTL are always
+        * armed by the CURBASE write only.
+        */
+       if (plane->cursor.base != base ||
+           plane->cursor.size != fbc_ctl ||
+           plane->cursor.cntl != cntl) {
+               I915_WRITE_FW(CURCNTR(pipe), cntl);
+               if (HAS_CUR_FBC(dev_priv))
+                       I915_WRITE_FW(CUR_FBC_CTL(pipe), fbc_ctl);
+               I915_WRITE_FW(CURPOS(pipe), pos);
+               I915_WRITE_FW(CURBASE(pipe), base);
+
+               plane->cursor.base = base;
+               plane->cursor.size = fbc_ctl;
+               plane->cursor.cntl = cntl;
        } else {
-               switch (width | height) {
-               case 256:
-               case 128:
-                       if (IS_GEN2(dev_priv))
-                               return false;
-               case 64:
-                       break;
-               default:
-                       return false;
-               }
+               I915_WRITE_FW(CURPOS(pipe), pos);
+               I915_WRITE_FW(CURBASE(pipe), base);
        }
 
-       return true;
+       POSTING_READ_FW(CURBASE(pipe));
+
+       spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 }
 
+static void i9xx_disable_cursor(struct intel_plane *plane,
+                               struct intel_crtc *crtc)
+{
+       i9xx_update_cursor(plane, NULL, NULL);
+}
+
+
 /* VESA 640x480x72Hz mode to set on the pipe */
 static struct drm_display_mode load_detect_mode = {
        DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 31500, 640, 664,
@@ -9576,6 +9794,7 @@ int intel_get_load_detect_pipe(struct drm_connector *connector,
         */
        if (!crtc) {
                DRM_DEBUG_KMS("no pipe available for load-detect\n");
+               ret = -ENODEV;
                goto fail;
        }
 
@@ -9632,6 +9851,7 @@ found:
                DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
        if (IS_ERR(fb)) {
                DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
+               ret = PTR_ERR(fb);
                goto fail;
        }
 
@@ -10863,21 +11083,21 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
                         turn_off, turn_on, mode_changed);
 
        if (turn_on) {
-               if (INTEL_GEN(dev_priv) < 5)
+               if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
                        pipe_config->update_wm_pre = true;
 
                /* must disable cxsr around plane enable/disable */
                if (plane->id != PLANE_CURSOR)
                        pipe_config->disable_cxsr = true;
        } else if (turn_off) {
-               if (INTEL_GEN(dev_priv) < 5)
+               if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
                        pipe_config->update_wm_post = true;
 
                /* must disable cxsr around plane enable/disable */
                if (plane->id != PLANE_CURSOR)
                        pipe_config->disable_cxsr = true;
        } else if (intel_wm_need_update(&plane->base, plane_state)) {
-               if (INTEL_GEN(dev_priv) < 5) {
+               if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv)) {
                        /* FIXME bollocks */
                        pipe_config->update_wm_pre = true;
                        pipe_config->update_wm_post = true;
@@ -11002,6 +11222,9 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
                if (mode_changed)
                        ret = skl_update_scaler_crtc(pipe_config);
 
+               if (!ret)
+                       ret = skl_check_pipe_max_pixel_rate(intel_crtc,
+                                                           pipe_config);
                if (!ret)
                        ret = intel_atomic_setup_scalers(dev_priv, intel_crtc,
                                                         pipe_config);
@@ -11226,6 +11449,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
 {
        struct drm_device *dev = state->dev;
        struct drm_connector *connector;
+       struct drm_connector_list_iter conn_iter;
        unsigned int used_ports = 0;
        unsigned int used_mst_ports = 0;
 
@@ -11234,7 +11458,8 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
         * list to detect the problem on ddi platforms
         * where there's just one encoder per digital port.
         */
-       drm_for_each_connector(connector, dev) {
+       drm_connector_list_iter_begin(dev, &conn_iter);
+       drm_for_each_connector_iter(connector, &conn_iter) {
                struct drm_connector_state *connector_state;
                struct intel_encoder *encoder;
 
@@ -11273,6 +11498,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state)
                        break;
                }
        }
+       drm_connector_list_iter_end(&conn_iter);
 
        /* can't mix MST and SST/HDMI on the same port */
        if (used_ports & used_mst_ports)
@@ -11301,7 +11527,8 @@ 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;
-       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+       if (IS_G4X(dev_priv) ||
+           IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                wm_state = crtc_state->wm;
 
        /* Keep base drm_crtc_state intact, only clear our extended struct */
@@ -11313,7 +11540,8 @@ 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;
-       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+       if (IS_G4X(dev_priv) ||
+           IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                crtc_state->wm = wm_state;
 }
 
@@ -11454,12 +11682,6 @@ intel_modeset_update_crtc_state(struct drm_atomic_state *state)
        for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
                to_intel_crtc(crtc)->config = to_intel_crtc_state(new_crtc_state);
 
-               /* Update hwmode for vblank functions */
-               if (new_crtc_state->active)
-                       crtc->hwmode = new_crtc_state->adjusted_mode;
-               else
-                       crtc->hwmode.crtc_clock = 0;
-
                /*
                 * Update legacy state to satisfy fbc code. This can
                 * be removed when fbc uses the atomic state.
@@ -11881,7 +12103,7 @@ static void verify_wm_state(struct drm_crtc *crtc,
         * allocation. In that case since the ddb allocation will be updated
         * once the plane becomes visible, we can skip this check
         */
-       if (intel_crtc->cursor_addr) {
+       if (1) {
                hw_plane_wm = &hw_wm.planes[PLANE_CURSOR];
                sw_plane_wm = &sw_wm->planes[PLANE_CURSOR];
 
@@ -11937,11 +12159,15 @@ verify_connector_state(struct drm_device *dev,
 
        for_each_new_connector_in_state(state, connector, new_conn_state, i) {
                struct drm_encoder *encoder = connector->encoder;
+               struct drm_crtc_state *crtc_state = NULL;
 
                if (new_conn_state->crtc != crtc)
                        continue;
 
-               intel_connector_verify_state(to_intel_connector(connector));
+               if (crtc)
+                       crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc);
+
+               intel_connector_verify_state(crtc_state, new_conn_state);
 
                I915_STATE_WARN(new_conn_state->best_encoder != encoder,
                     "connector's atomic encoder doesn't match legacy encoder\n");
@@ -12021,9 +12247,8 @@ verify_crtc_state(struct drm_crtc *crtc,
 
        active = dev_priv->display.get_pipe_config(intel_crtc, pipe_config);
 
-       /* hw state is inconsistent with the pipe quirk */
-       if ((intel_crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) ||
-           (intel_crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))
+       /* we keep both pipes enabled on 830 */
+       if (IS_I830(dev_priv))
                active = new_crtc_state->active;
 
        I915_STATE_WARN(new_crtc_state->active != active,
@@ -12059,7 +12284,7 @@ verify_crtc_state(struct drm_crtc *crtc,
 
        intel_pipe_config_sanity_check(dev_priv, pipe_config);
 
-       sw_config = to_intel_crtc_state(crtc->state);
+       sw_config = to_intel_crtc_state(new_crtc_state);
        if (!intel_pipe_config_compare(dev_priv, sw_config,
                                       pipe_config, false)) {
                I915_STATE_WARN(1, "pipe state doesn't match!\n");
@@ -12932,8 +13157,16 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 
        drm_atomic_helper_commit_hw_done(state);
 
-       if (intel_state->modeset)
+       if (intel_state->modeset) {
+               /* As one of the primary mmio accessors, KMS has a high
+                * likelihood of triggering bugs in unclaimed access. After we
+                * finish modesetting, see if an error has been flagged, and if
+                * so enable debugging for the next modeset - and hope we catch
+                * the culprit.
+                */
+               intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
                intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
+       }
 
        mutex_lock(&dev->struct_mutex);
        drm_atomic_helper_cleanup_planes(dev, state);
@@ -12943,19 +13176,6 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 
        drm_atomic_state_put(state);
 
-       /* As one of the primary mmio accessors, KMS has a high likelihood
-        * of triggering bugs in unclaimed access. After we finish
-        * modesetting, see if an error has been flagged, and if so
-        * enable debugging for the next modeset - and hope we catch
-        * the culprit.
-        *
-        * XXX note that we assume display power is on at this point.
-        * This might hold true now but we need to add pm helper to check
-        * unclaimed only when the hardware is on, as atomic commits
-        * can happen also when the device is completely off.
-        */
-       intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
-
        intel_atomic_helper_free_state(dev_priv);
 }
 
@@ -13087,43 +13307,6 @@ static int intel_atomic_commit(struct drm_device *dev,
        return 0;
 }
 
-void intel_crtc_restore_mode(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_atomic_state *state;
-       struct drm_crtc_state *crtc_state;
-       int ret;
-
-       state = drm_atomic_state_alloc(dev);
-       if (!state) {
-               DRM_DEBUG_KMS("[CRTC:%d:%s] crtc restore failed, out of memory",
-                             crtc->base.id, crtc->name);
-               return;
-       }
-
-       state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
-
-retry:
-       crtc_state = drm_atomic_get_crtc_state(state, crtc);
-       ret = PTR_ERR_OR_ZERO(crtc_state);
-       if (!ret) {
-               if (!crtc_state->active)
-                       goto out;
-
-               crtc_state->mode_changed = true;
-               ret = drm_atomic_commit(state);
-       }
-
-       if (ret == -EDEADLK) {
-               drm_atomic_state_clear(state);
-               drm_modeset_backoff(state->acquire_ctx);
-               goto retry;
-       }
-
-out:
-       drm_atomic_state_put(state);
-}
-
 static const struct drm_crtc_funcs intel_crtc_funcs = {
        .gamma_set = drm_atomic_helper_legacy_gamma_set,
        .set_config = drm_atomic_helper_set_config,
@@ -13164,7 +13347,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
        if (obj) {
                if (plane->type == DRM_PLANE_TYPE_CURSOR &&
                    INTEL_INFO(dev_priv)->cursor_needs_physical) {
-                       const int align = IS_I830(dev_priv) ? 16 * 1024 : 256;
+                       const int align = intel_cursor_alignment(dev_priv);
 
                        ret = i915_gem_object_attach_phys(obj, align);
                        if (ret) {
@@ -13294,11 +13477,11 @@ skl_max_scale(struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state
 }
 
 static int
-intel_check_primary_plane(struct drm_plane *plane,
+intel_check_primary_plane(struct intel_plane *plane,
                          struct intel_crtc_state *crtc_state,
                          struct intel_plane_state *state)
 {
-       struct drm_i915_private *dev_priv = to_i915(plane->dev);
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        struct drm_crtc *crtc = state->base.crtc;
        int min_scale = DRM_PLANE_HELPER_NO_SCALING;
        int max_scale = DRM_PLANE_HELPER_NO_SCALING;
@@ -13477,7 +13660,7 @@ intel_legacy_cursor_update(struct drm_plane *plane,
                goto out_free;
 
        if (INTEL_INFO(dev_priv)->cursor_needs_physical) {
-               int align = IS_I830(dev_priv) ? 16 * 1024 : 256;
+               int align = intel_cursor_alignment(dev_priv);
 
                ret = i915_gem_object_attach_phys(intel_fb_obj(fb), align);
                if (ret) {
@@ -13513,12 +13696,12 @@ intel_legacy_cursor_update(struct drm_plane *plane,
 
        if (plane->state->visible) {
                trace_intel_update_plane(plane, to_intel_crtc(crtc));
-               intel_plane->update_plane(plane,
+               intel_plane->update_plane(intel_plane,
                                          to_intel_crtc_state(crtc->state),
                                          to_intel_plane_state(plane->state));
        } else {
                trace_intel_disable_plane(plane, to_intel_crtc(crtc));
-               intel_plane->disable_plane(plane, crtc);
+               intel_plane->disable_plane(intel_plane, to_intel_crtc(crtc));
        }
 
        intel_cleanup_plane_fb(plane, new_plane_state);
@@ -13632,22 +13815,22 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 
        if (INTEL_GEN(dev_priv) >= 9) {
                supported_rotations =
-                       DRM_ROTATE_0 | DRM_ROTATE_90 |
-                       DRM_ROTATE_180 | DRM_ROTATE_270;
+                       DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
+                       DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
        } else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
                supported_rotations =
-                       DRM_ROTATE_0 | DRM_ROTATE_180 |
-                       DRM_REFLECT_X;
+                       DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
+                       DRM_MODE_REFLECT_X;
        } else if (INTEL_GEN(dev_priv) >= 4) {
                supported_rotations =
-                       DRM_ROTATE_0 | DRM_ROTATE_180;
+                       DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
        } else {
-               supported_rotations = DRM_ROTATE_0;
+               supported_rotations = DRM_MODE_ROTATE_0;
        }
 
        if (INTEL_GEN(dev_priv) >= 4)
                drm_plane_create_rotation_property(&primary->base,
-                                                  DRM_ROTATE_0,
+                                                  DRM_MODE_ROTATE_0,
                                                   supported_rotations);
 
        drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
@@ -13661,107 +13844,9 @@ fail:
        return ERR_PTR(ret);
 }
 
-static int
-intel_check_cursor_plane(struct drm_plane *plane,
-                        struct intel_crtc_state *crtc_state,
-                        struct intel_plane_state *state)
-{
-       struct drm_i915_private *dev_priv = to_i915(plane->dev);
-       struct drm_framebuffer *fb = state->base.fb;
-       struct drm_i915_gem_object *obj = intel_fb_obj(fb);
-       enum pipe pipe = to_intel_plane(plane)->pipe;
-       unsigned stride;
-       int ret;
-
-       ret = drm_plane_helper_check_state(&state->base,
-                                          &state->clip,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          DRM_PLANE_HELPER_NO_SCALING,
-                                          true, true);
-       if (ret)
-               return ret;
-
-       /* if we want to turn off the cursor ignore width and height */
-       if (!obj)
-               return 0;
-
-       /* Check for which cursor types we support */
-       if (!cursor_size_ok(dev_priv, state->base.crtc_w,
-                           state->base.crtc_h)) {
-               DRM_DEBUG("Cursor dimension %dx%d not supported\n",
-                         state->base.crtc_w, state->base.crtc_h);
-               return -EINVAL;
-       }
-
-       stride = roundup_pow_of_two(state->base.crtc_w) * 4;
-       if (obj->base.size < stride * state->base.crtc_h) {
-               DRM_DEBUG_KMS("buffer is too small\n");
-               return -ENOMEM;
-       }
-
-       if (fb->modifier != DRM_FORMAT_MOD_LINEAR) {
-               DRM_DEBUG_KMS("cursor cannot be tiled\n");
-               return -EINVAL;
-       }
-
-       /*
-        * There's something wrong with the cursor on CHV pipe C.
-        * If it straddles the left edge of the screen then
-        * moving it away from the edge or disabling it often
-        * results in a pipe underrun, and often that can lead to
-        * dead pipe (constant underrun reported, and it scans
-        * out just a solid color). To recover from that, the
-        * display power well must be turned off and on again.
-        * Refuse the put the cursor into that compromised position.
-        */
-       if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
-           state->base.visible && state->base.crtc_x < 0) {
-               DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n");
-               return -EINVAL;
-       }
-
-       if (IS_I845G(dev_priv) || IS_I865G(dev_priv))
-               state->ctl = i845_cursor_ctl(crtc_state, state);
-       else
-               state->ctl = i9xx_cursor_ctl(crtc_state, state);
-
-       return 0;
-}
-
-static void
-intel_disable_cursor_plane(struct drm_plane *plane,
-                          struct drm_crtc *crtc)
-{
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-       intel_crtc->cursor_addr = 0;
-       intel_crtc_update_cursor(crtc, NULL);
-}
-
-static void
-intel_update_cursor_plane(struct drm_plane *plane,
-                         const struct intel_crtc_state *crtc_state,
-                         const struct intel_plane_state *state)
-{
-       struct drm_crtc *crtc = crtc_state->base.crtc;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_i915_private *dev_priv = to_i915(plane->dev);
-       struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb);
-       uint32_t addr;
-
-       if (!obj)
-               addr = 0;
-       else if (!INTEL_INFO(dev_priv)->cursor_needs_physical)
-               addr = intel_plane_ggtt_offset(state);
-       else
-               addr = obj->phys_handle->busaddr;
-
-       intel_crtc->cursor_addr = addr;
-       intel_crtc_update_cursor(crtc, state);
-}
-
 static struct intel_plane *
-intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
+intel_cursor_plane_create(struct drm_i915_private *dev_priv,
+                         enum pipe pipe)
 {
        struct intel_plane *cursor = NULL;
        struct intel_plane_state *state = NULL;
@@ -13787,9 +13872,22 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
        cursor->plane = pipe;
        cursor->id = PLANE_CURSOR;
        cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe);
-       cursor->check_plane = intel_check_cursor_plane;
-       cursor->update_plane = intel_update_cursor_plane;
-       cursor->disable_plane = intel_disable_cursor_plane;
+
+       if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
+               cursor->update_plane = i845_update_cursor;
+               cursor->disable_plane = i845_disable_cursor;
+               cursor->check_plane = i845_check_cursor;
+       } else {
+               cursor->update_plane = i9xx_update_cursor;
+               cursor->disable_plane = i9xx_disable_cursor;
+               cursor->check_plane = i9xx_check_cursor;
+       }
+
+       cursor->cursor.base = ~0;
+       cursor->cursor.cntl = ~0;
+
+       if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
+               cursor->cursor.size = ~0;
 
        ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
                                       0, &intel_cursor_plane_funcs,
@@ -13802,9 +13900,9 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 
        if (INTEL_GEN(dev_priv) >= 4)
                drm_plane_create_rotation_property(&cursor->base,
-                                                  DRM_ROTATE_0,
-                                                  DRM_ROTATE_0 |
-                                                  DRM_ROTATE_180);
+                                                  DRM_MODE_ROTATE_0,
+                                                  DRM_MODE_ROTATE_0 |
+                                                  DRM_MODE_ROTATE_180);
 
        if (INTEL_GEN(dev_priv) >= 9)
                state->scaler_id = -1;
@@ -13898,10 +13996,6 @@ static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
        intel_crtc->pipe = pipe;
        intel_crtc->plane = primary->plane;
 
-       intel_crtc->cursor_base = ~0;
-       intel_crtc->cursor_cntl = ~0;
-       intel_crtc->cursor_size = ~0;
-
        /* initialize shared scalers */
        intel_crtc_init_scalers(intel_crtc, crtc_state);
 
@@ -14441,7 +14535,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
        case DRM_FORMAT_UYVY:
        case DRM_FORMAT_YVYU:
        case DRM_FORMAT_VYUY:
-               if (INTEL_GEN(dev_priv) < 5) {
+               if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv)) {
                        DRM_DEBUG_KMS("unsupported pixel format: %s\n",
                                      drm_get_format_name(mode_cmd->pixel_format, &format_name));
                        goto err;
@@ -14652,27 +14746,6 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv)
        }
 }
 
-/*
- * Some BIOSes insist on assuming the GPU's pipe A is enabled at suspend,
- * resume, or other times.  This quirk makes sure that's the case for
- * affected systems.
- */
-static void quirk_pipea_force(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = to_i915(dev);
-
-       dev_priv->quirks |= QUIRK_PIPEA_FORCE;
-       DRM_INFO("applying pipe a force quirk\n");
-}
-
-static void quirk_pipeb_force(struct drm_device *dev)
-{
-       struct drm_i915_private *dev_priv = to_i915(dev);
-
-       dev_priv->quirks |= QUIRK_PIPEB_FORCE;
-       DRM_INFO("applying pipe b force quirk\n");
-}
-
 /*
  * Some machines (Lenovo U160) do not work with SSC on LVDS for some reason
  */
@@ -14738,18 +14811,6 @@ static const struct intel_dmi_quirk intel_dmi_quirks[] = {
 };
 
 static struct intel_quirk intel_quirks[] = {
-       /* Toshiba Protege R-205, S-209 needs pipe A force quirk */
-       { 0x2592, 0x1179, 0x0001, quirk_pipea_force },
-
-       /* ThinkPad T60 needs pipe A force quirk (bug #16494) */
-       { 0x2782, 0x17aa, 0x201a, quirk_pipea_force },
-
-       /* 830 needs to leave pipe A & dpll A up */
-       { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
-
-       /* 830 needs to leave pipe B & dpll B up */
-       { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipeb_force },
-
        /* Lenovo U160 cannot use SSC on LVDS */
        { 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable },
 
@@ -14953,6 +15014,7 @@ int intel_modeset_init(struct drm_device *dev)
 
        dev->mode_config.funcs = &intel_mode_funcs;
 
+       init_llist_head(&dev_priv->atomic_helper.free_list);
        INIT_WORK(&dev_priv->atomic_helper.free_work,
                  intel_atomic_helper_free_state_worker);
 
@@ -15069,35 +15131,89 @@ int intel_modeset_init(struct drm_device *dev)
        return 0;
 }
 
-static void intel_enable_pipe_a(struct drm_device *dev,
-                               struct drm_modeset_acquire_ctx *ctx)
+void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
-       struct intel_connector *connector;
-       struct drm_connector_list_iter conn_iter;
-       struct drm_connector *crt = NULL;
-       struct intel_load_detect_pipe load_detect_temp;
-       int ret;
+       /* 640x480@60Hz, ~25175 kHz */
+       struct dpll clock = {
+               .m1 = 18,
+               .m2 = 7,
+               .p1 = 13,
+               .p2 = 4,
+               .n = 2,
+       };
+       u32 dpll, fp;
+       int i;
 
-       /* We can't just switch on the pipe A, we need to set things up with a
-        * proper mode and output configuration. As a gross hack, enable pipe A
-        * by enabling the load detect pipe once. */
-       drm_connector_list_iter_begin(dev, &conn_iter);
-       for_each_intel_connector_iter(connector, &conn_iter) {
-               if (connector->encoder->type == INTEL_OUTPUT_ANALOG) {
-                       crt = &connector->base;
-                       break;
-               }
+       WARN_ON(i9xx_calc_dpll_params(48000, &clock) != 25154);
+
+       DRM_DEBUG_KMS("enabling pipe %c due to force quirk (vco=%d dot=%d)\n",
+                     pipe_name(pipe), clock.vco, clock.dot);
+
+       fp = i9xx_dpll_compute_fp(&clock);
+       dpll = (I915_READ(DPLL(pipe)) & DPLL_DVO_2X_MODE) |
+               DPLL_VGA_MODE_DIS |
+               ((clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT) |
+               PLL_P2_DIVIDE_BY_4 |
+               PLL_REF_INPUT_DREFCLK |
+               DPLL_VCO_ENABLE;
+
+       I915_WRITE(FP0(pipe), fp);
+       I915_WRITE(FP1(pipe), fp);
+
+       I915_WRITE(HTOTAL(pipe), (640 - 1) | ((800 - 1) << 16));
+       I915_WRITE(HBLANK(pipe), (640 - 1) | ((800 - 1) << 16));
+       I915_WRITE(HSYNC(pipe), (656 - 1) | ((752 - 1) << 16));
+       I915_WRITE(VTOTAL(pipe), (480 - 1) | ((525 - 1) << 16));
+       I915_WRITE(VBLANK(pipe), (480 - 1) | ((525 - 1) << 16));
+       I915_WRITE(VSYNC(pipe), (490 - 1) | ((492 - 1) << 16));
+       I915_WRITE(PIPESRC(pipe), ((640 - 1) << 16) | (480 - 1));
+
+       /*
+        * Apparently we need to have VGA mode enabled prior to changing
+        * the P1/P2 dividers. Otherwise the DPLL will keep using the old
+        * dividers, even though the register value does change.
+        */
+       I915_WRITE(DPLL(pipe), dpll & ~DPLL_VGA_MODE_DIS);
+       I915_WRITE(DPLL(pipe), dpll);
+
+       /* Wait for the clocks to stabilize. */
+       POSTING_READ(DPLL(pipe));
+       udelay(150);
+
+       /* The pixel multiplier can only be updated once the
+        * DPLL is enabled and the clocks are stable.
+        *
+        * So write it again.
+        */
+       I915_WRITE(DPLL(pipe), dpll);
+
+       /* We do this three times for luck */
+       for (i = 0; i < 3 ; i++) {
+               I915_WRITE(DPLL(pipe), dpll);
+               POSTING_READ(DPLL(pipe));
+               udelay(150); /* wait for warmup */
        }
-       drm_connector_list_iter_end(&conn_iter);
 
-       if (!crt)
-               return;
+       I915_WRITE(PIPECONF(pipe), PIPECONF_ENABLE | PIPECONF_PROGRESSIVE);
+       POSTING_READ(PIPECONF(pipe));
+}
+
+void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+       DRM_DEBUG_KMS("disabling pipe %c due to force quirk\n",
+                     pipe_name(pipe));
 
-       ret = intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, ctx);
-       WARN(ret < 0, "All modeset mutexes are locked, but intel_get_load_detect_pipe failed\n");
+       assert_plane_disabled(dev_priv, PLANE_A);
+       assert_plane_disabled(dev_priv, PLANE_B);
 
-       if (ret > 0)
-               intel_release_load_detect_pipe(crt, &load_detect_temp, ctx);
+       I915_WRITE(PIPECONF(pipe), 0);
+       POSTING_READ(PIPECONF(pipe));
+
+       if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
+               DRM_ERROR("pipe %c off wait timed out\n", pipe_name(pipe));
+
+       I915_WRITE(DPLL(pipe), DPLL_VGA_MODE_DIS);
+       POSTING_READ(DPLL(pipe));
 }
 
 static bool
@@ -15175,7 +15291,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
                                continue;
 
                        trace_intel_disable_plane(&plane->base, crtc);
-                       plane->disable_plane(&plane->base, &crtc->base);
+                       plane->disable_plane(plane, crtc);
                }
        }
 
@@ -15198,15 +15314,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
                crtc->plane = plane;
        }
 
-       if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
-           crtc->pipe == PIPE_A && !crtc->active) {
-               /* BIOS forgot to enable pipe A, this mostly happens after
-                * resume. Force-enable the pipe to fix this, the update_dpms
-                * call below we restore the pipe to the right state, but leave
-                * the required bits on. */
-               intel_enable_pipe_a(dev, ctx);
-       }
-
        /* Adjust the state of the output pipe according to whether we
         * have active connectors/encoders. */
        if (crtc->active && !intel_crtc_has_encoders(crtc))
@@ -15445,8 +15552,6 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                        to_intel_crtc_state(crtc->base.state);
                int pixclk = 0;
 
-               crtc->base.hwmode = crtc_state->base.adjusted_mode;
-
                memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
                if (crtc_state->base.active) {
                        intel_mode_from_pipe_config(&crtc->base.mode, crtc_state);
@@ -15476,7 +15581,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                        if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
                                pixclk = DIV_ROUND_UP(pixclk * 100, 95);
 
-                       drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
+                       drm_calc_timestamping_constants(&crtc->base,
+                                                       &crtc_state->base.adjusted_mode);
                        update_scanline_offset(crtc);
                }
 
@@ -15548,7 +15654,10 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
                pll->on = false;
        }
 
-       if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+       if (IS_G4X(dev_priv)) {
+               g4x_wm_get_hw_state(dev);
+               g4x_wm_sanitize(dev_priv);
+       } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
                vlv_wm_get_hw_state(dev);
                vlv_wm_sanitize(dev_priv);
        } else if (IS_GEN9(dev_priv)) {
@@ -15582,13 +15691,6 @@ void intel_display_resume(struct drm_device *dev)
        if (state)
                state->acquire_ctx = &ctx;
 
-       /*
-        * This is a cludge because with real atomic modeset mode_config.mutex
-        * won't be taken. Unfortunately some probed state like
-        * audio_codec_enable is still protected by mode_config.mutex, so lock
-        * it here for now.
-        */
-       mutex_lock(&dev->mode_config.mutex);
        drm_modeset_acquire_init(&ctx, 0);
 
        while (1) {
@@ -15604,7 +15706,6 @@ void intel_display_resume(struct drm_device *dev)
 
        drm_modeset_drop_locks(&ctx);
        drm_modeset_acquire_fini(&ctx);
-       mutex_unlock(&dev->mode_config.mutex);
 
        if (ret)
                DRM_ERROR("Restoring old state failed with %i\n", ret);