]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/i915/intel_display.c
drm/i915: Fix intel_crtc_mode_get() mode clock
[karo-tx-linux.git] / drivers / gpu / drm / i915 / intel_display.c
index 8b5fa95f9478d0e8a040c172fcde206ed357f49b..a3f21a508d0e1a176103dc4f822ebb99656f5689 100644 (file)
@@ -733,6 +733,23 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc,
        return true;
 }
 
+bool intel_crtc_active(struct drm_crtc *crtc)
+{
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+       /* Be paranoid as we can arrive here with only partial
+        * state retrieved from the hardware during setup.
+        *
+        * We can ditch the adjusted_mode.clock check as soon
+        * as Haswell has gained clock readout/fastboot support.
+        *
+        * We can ditch the crtc->fb check as soon as we can
+        * properly reconstruct framebuffers.
+        */
+       return intel_crtc->active && crtc->fb &&
+               intel_crtc->config.adjusted_mode.clock;
+}
+
 enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
                                             enum pipe pipe)
 {
@@ -2274,7 +2291,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                I915_WRITE(PIPESRC(intel_crtc->pipe),
                           ((crtc->mode.hdisplay - 1) << 16) |
                           (crtc->mode.vdisplay - 1));
-               if (!intel_crtc->config.pch_pfit.size &&
+               if (!intel_crtc->config.pch_pfit.enabled &&
                    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) ||
                     intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
                        I915_WRITE(PF_CTL(intel_crtc->pipe), 0);
@@ -3229,7 +3246,7 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int pipe = crtc->pipe;
 
-       if (crtc->config.pch_pfit.size) {
+       if (crtc->config.pch_pfit.enabled) {
                /* Force use of hard-coded filter coefficients
                 * as some pre-programmed values are broken,
                 * e.g. x201.
@@ -3369,6 +3386,7 @@ static void hsw_disable_ips(struct intel_crtc *crtc)
 
        assert_plane_enabled(dev_priv, crtc->plane);
        I915_WRITE(IPS_CTL, 0);
+       POSTING_READ(IPS_CTL);
 
        /* We need to wait for a vblank before we can disable the plane. */
        intel_wait_for_vblank(dev, crtc->pipe);
@@ -3454,7 +3472,7 @@ static void ironlake_pfit_disable(struct intel_crtc *crtc)
 
        /* To avoid upsetting the power well on haswell only disable the pfit if
         * it's in use. The hw state code will make sure we get this right. */
-       if (crtc->config.pch_pfit.size) {
+       if (crtc->config.pch_pfit.enabled) {
                I915_WRITE(PF_CTL(pipe), 0);
                I915_WRITE(PF_WIN_POS(pipe), 0);
                I915_WRITE(PF_WIN_SZ(pipe), 0);
@@ -4126,6 +4144,39 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
        struct drm_device *dev = crtc->base.dev;
        struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
 
+       /* FIXME should check pixel clock limits on all platforms */
+       if (INTEL_INFO(dev)->gen < 4) {
+               struct drm_i915_private *dev_priv = dev->dev_private;
+               int clock_limit =
+                       dev_priv->display.get_display_clock_speed(dev);
+
+               /*
+                * Enable pixel doubling when the dot clock
+                * is > 90% of the (display) core speed.
+                *
+                * GDG double wide on either pipe,
+                * otherwise pipe A only.
+                */
+               if ((crtc->pipe == PIPE_A || IS_I915G(dev)) &&
+                   adjusted_mode->clock > clock_limit * 9 / 10) {
+                       clock_limit *= 2;
+                       pipe_config->double_wide = true;
+               }
+
+               if (adjusted_mode->clock > clock_limit * 9 / 10)
+                       return -EINVAL;
+       }
+
+       /*
+        * Pipe horizontal size must be even in:
+        * - DVO ganged mode
+        * - LVDS dual channel mode
+        * - Double wide pipe
+        */
+       if ((intel_pipe_has_type(&crtc->base, INTEL_OUTPUT_LVDS) &&
+            intel_is_dual_link_lvds(dev)) || pipe_config->double_wide)
+               pipe_config->pipe_src_w &= ~1;
+
        /* Cantiga+ cannot handle modes with a hsync front porch of 0.
         * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
         */
@@ -4289,28 +4340,6 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
                && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);
 }
 
-static int vlv_get_refclk(struct drm_crtc *crtc)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       int refclk = 27000; /* for DP & HDMI */
-
-       return 100000; /* only one validated so far */
-
-       if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) {
-               refclk = 96000;
-       } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-               if (intel_panel_use_ssc(dev_priv))
-                       refclk = 100000;
-               else
-                       refclk = 96000;
-       } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
-               refclk = 100000;
-       }
-
-       return refclk;
-}
-
 static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
 {
        struct drm_device *dev = crtc->dev;
@@ -4318,7 +4347,7 @@ static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors)
        int refclk;
 
        if (IS_VALLEYVIEW(dev)) {
-               refclk = vlv_get_refclk(crtc);
+               refclk = 100000;
        } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
            intel_panel_use_ssc(dev_priv) && num_connectors < 2) {
                refclk = dev_priv->vbt.lvds_ssc_freq * 1000;
@@ -4679,7 +4708,6 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
        enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder;
        struct drm_display_mode *adjusted_mode =
                &intel_crtc->config.adjusted_mode;
-       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        uint32_t vsyncshift, crtc_vtotal, crtc_vblank_end;
 
        /* We need to be careful not to changed the adjusted mode, for otherwise
@@ -4732,7 +4760,8 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
         * always be the user's requested size.
         */
        I915_WRITE(PIPESRC(pipe),
-                  ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
+                  ((intel_crtc->config.pipe_src_w - 1) << 16) |
+                  (intel_crtc->config.pipe_src_h - 1));
 }
 
 static void intel_get_pipe_timings(struct intel_crtc *crtc,
@@ -4770,8 +4799,11 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc,
        }
 
        tmp = I915_READ(PIPESRC(crtc->pipe));
-       pipe_config->requested_mode.vdisplay = (tmp & 0xffff) + 1;
-       pipe_config->requested_mode.hdisplay = ((tmp >> 16) & 0xffff) + 1;
+       pipe_config->pipe_src_h = (tmp & 0xffff) + 1;
+       pipe_config->pipe_src_w = ((tmp >> 16) & 0xffff) + 1;
+
+       pipe_config->requested_mode.vdisplay = pipe_config->pipe_src_h;
+       pipe_config->requested_mode.hdisplay = pipe_config->pipe_src_w;
 }
 
 static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc,
@@ -4803,17 +4835,12 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
 
        pipeconf = 0;
 
-       if (intel_crtc->pipe == 0 && INTEL_INFO(dev)->gen < 4) {
-               /* Enable pixel doubling when the dot clock is > 90% of the (display)
-                * core speed.
-                *
-                * XXX: No double-wide on 915GM pipe B. Is that the only reason for the
-                * pipe == 0 check?
-                */
-               if (intel_crtc->config.adjusted_mode.clock >
-                   dev_priv->display.get_display_clock_speed(dev) * 9 / 10)
-                       pipeconf |= PIPECONF_DOUBLE_WIDE;
-       }
+       if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
+           I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE)
+               pipeconf |= PIPECONF_ENABLE;
+
+       if (intel_crtc->config.double_wide)
+               pipeconf |= PIPECONF_DOUBLE_WIDE;
 
        /* only g4x and later have fancy bpc/dither controls */
        if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) {
@@ -4867,7 +4894,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct drm_display_mode *mode = &intel_crtc->config.requested_mode;
        int pipe = intel_crtc->pipe;
        int plane = intel_crtc->plane;
        int refclk, num_connectors = 0;
@@ -4911,10 +4937,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
                }
        }
 
-       /* Ensure that the cursor is valid for the new mode before changing... */
-       intel_crtc_update_cursor(crtc, true);
-
-       if (!is_dsi && is_lvds && dev_priv->lvds_downclock_avail) {
+       if (is_lvds && dev_priv->lvds_downclock_avail) {
                /*
                 * Ensure we match the reduced clock's P to the target clock.
                 * If the clocks don't match, we can't switch the display clock
@@ -4966,8 +4989,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
         * which should always be the user's requested size.
         */
        I915_WRITE(DSPSIZE(plane),
-                  ((mode->vdisplay - 1) << 16) |
-                  (mode->hdisplay - 1));
+                  ((intel_crtc->config.pipe_src_h - 1) << 16) |
+                  (intel_crtc->config.pipe_src_w - 1));
        I915_WRITE(DSPPOS(plane), 0);
 
        i9xx_set_pipeconf(intel_crtc);
@@ -5037,6 +5060,9 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
                }
        }
 
+       if (INTEL_INFO(dev)->gen < 4)
+               pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE;
+
        intel_get_pipe_timings(crtc, pipe_config);
 
        i9xx_get_pfit_config(crtc, pipe_config);
@@ -5821,9 +5847,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
                intel_crtc->config.dpll.p2 = clock.p2;
        }
 
-       /* Ensure that the cursor is valid for the new mode before changing... */
-       intel_crtc_update_cursor(crtc, true);
-
        /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */
        if (intel_crtc->config.has_pch_encoder) {
                fp = i9xx_dpll_compute_fp(&intel_crtc->config.dpll);
@@ -5954,6 +5977,7 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc,
        tmp = I915_READ(PF_CTL(crtc->pipe));
 
        if (tmp & PF_ENABLE) {
+               pipe_config->pch_pfit.enabled = true;
                pipe_config->pch_pfit.pos = I915_READ(PF_WIN_POS(crtc->pipe));
                pipe_config->pch_pfit.size = I915_READ(PF_WIN_SZ(crtc->pipe));
 
@@ -6116,7 +6140,10 @@ void hsw_disable_lcpll(struct drm_i915_private *dev_priv,
 
        val = I915_READ(D_COMP);
        val |= D_COMP_COMP_DISABLE;
-       I915_WRITE(D_COMP, val);
+       mutex_lock(&dev_priv->rps.hw_lock);
+       if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val))
+               DRM_ERROR("Failed to disable D_COMP\n");
+       mutex_unlock(&dev_priv->rps.hw_lock);
        POSTING_READ(D_COMP);
        ndelay(100);
 
@@ -6158,7 +6185,10 @@ void hsw_restore_lcpll(struct drm_i915_private *dev_priv)
        val = I915_READ(D_COMP);
        val |= D_COMP_COMP_FORCE;
        val &= ~D_COMP_COMP_DISABLE;
-       I915_WRITE(D_COMP, val);
+       mutex_lock(&dev_priv->rps.hw_lock);
+       if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val))
+               DRM_ERROR("Failed to enable D_COMP\n");
+       mutex_unlock(&dev_priv->rps.hw_lock);
        POSTING_READ(D_COMP);
 
        val = I915_READ(LCPLL_CTL);
@@ -6350,7 +6380,7 @@ static void haswell_modeset_global_resources(struct drm_device *dev)
                if (!crtc->base.enabled)
                        continue;
 
-               if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.size ||
+               if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.enabled ||
                    crtc->config.cpu_transcoder != TRANSCODER_EDP)
                        enable = true;
        }
@@ -6373,9 +6403,6 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
        if (!intel_ddi_pll_mode_set(crtc))
                return -EINVAL;
 
-       /* Ensure that the cursor is valid for the new mode before changing... */
-       intel_crtc_update_cursor(crtc, true);
-
        if (intel_crtc->config.has_dp_encoder)
                intel_dp_set_m_n(intel_crtc);
 
@@ -6606,15 +6633,15 @@ static void haswell_write_eld(struct drm_connector *connector,
 
        /* Set ELD valid state */
        tmp = I915_READ(aud_cntrl_st2);
-       DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%8x\n", tmp);
+       DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%08x\n", tmp);
        tmp |= (AUDIO_ELD_VALID_A << (pipe * 4));
        I915_WRITE(aud_cntrl_st2, tmp);
        tmp = I915_READ(aud_cntrl_st2);
-       DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%8x\n", tmp);
+       DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%08x\n", tmp);
 
        /* Enable HDMI mode */
        tmp = I915_READ(aud_config);
-       DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%8x\n", tmp);
+       DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%08x\n", tmp);
        /* clear N_programing_enable and N_value_index */
        tmp &= ~(AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_N_PROG_ENABLE);
        I915_WRITE(aud_config, tmp);
@@ -6902,23 +6929,20 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
        int pipe = intel_crtc->pipe;
        int x = intel_crtc->cursor_x;
        int y = intel_crtc->cursor_y;
-       u32 base, pos;
+       u32 base = 0, pos = 0;
        bool visible;
 
-       pos = 0;
-
-       if (on && crtc->enabled && crtc->fb) {
+       if (on)
                base = intel_crtc->cursor_addr;
-               if (x > (int) crtc->fb->width)
-                       base = 0;
 
-               if (y > (int) crtc->fb->height)
-                       base = 0;
-       } else
+       if (x >= intel_crtc->config.pipe_src_w)
+               base = 0;
+
+       if (y >= intel_crtc->config.pipe_src_h)
                base = 0;
 
        if (x < 0) {
-               if (x + intel_crtc->cursor_width < 0)
+               if (x + intel_crtc->cursor_width <= 0)
                        base = 0;
 
                pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
@@ -6927,7 +6951,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
        pos |= x << CURSOR_X_SHIFT;
 
        if (y < 0) {
-               if (y + intel_crtc->cursor_height < 0)
+               if (y + intel_crtc->cursor_height <= 0)
                        base = 0;
 
                pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
@@ -7053,7 +7077,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
        intel_crtc->cursor_width = width;
        intel_crtc->cursor_height = height;
 
-       intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
+       if (intel_crtc->active)
+               intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
 
        return 0;
 fail_unpin:
@@ -7072,7 +7097,8 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
        intel_crtc->cursor_x = x;
        intel_crtc->cursor_y = y;
 
-       intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
+       if (intel_crtc->active)
+               intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL);
 
        return 0;
 }
@@ -7517,7 +7543,7 @@ 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.adjusted_mode.clock;
+       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;
@@ -7969,7 +7995,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
        int len, ret;
 
        ring = obj->ring;
-       if (ring == NULL || ring->id != RCS)
+       if (IS_VALLEYVIEW(dev) || ring == NULL || ring->id != RCS)
                ring = &dev_priv->ring[BCS];
 
        ret = intel_pin_and_fence_fb_obj(dev, obj, ring);
@@ -8071,7 +8097,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
             fb->pitches[0] != crtc->fb->pitches[0]))
                return -EINVAL;
 
-       work = kzalloc(sizeof *work, GFP_KERNEL);
+       work = kzalloc(sizeof(*work), GFP_KERNEL);
        if (work == NULL)
                return -ENOMEM;
 
@@ -8306,6 +8332,17 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc,
        return bpp;
 }
 
+static void intel_dump_crtc_timings(const struct drm_display_mode *mode)
+{
+       DRM_DEBUG_KMS("crtc timings: %d %d %d %d %d %d %d %d %d, "
+                       "type: 0x%x flags: 0x%x\n",
+               mode->clock,
+               mode->crtc_hdisplay, mode->crtc_hsync_start,
+               mode->crtc_hsync_end, mode->crtc_htotal,
+               mode->crtc_vdisplay, mode->crtc_vsync_start,
+               mode->crtc_vsync_end, mode->crtc_vtotal, mode->type, mode->flags);
+}
+
 static void intel_dump_pipe_config(struct intel_crtc *crtc,
                                   struct intel_crtc_config *pipe_config,
                                   const char *context)
@@ -8331,15 +8368,20 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
        drm_mode_debug_printmodeline(&pipe_config->requested_mode);
        DRM_DEBUG_KMS("adjusted mode:\n");
        drm_mode_debug_printmodeline(&pipe_config->adjusted_mode);
+       intel_dump_crtc_timings(&pipe_config->adjusted_mode);
        DRM_DEBUG_KMS("port clock: %d\n", pipe_config->port_clock);
+       DRM_DEBUG_KMS("pipe src size: %dx%d\n",
+                     pipe_config->pipe_src_w, pipe_config->pipe_src_h);
        DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n",
                      pipe_config->gmch_pfit.control,
                      pipe_config->gmch_pfit.pgm_ratios,
                      pipe_config->gmch_pfit.lvds_border_bits);
-       DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x\n",
+       DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x, %s\n",
                      pipe_config->pch_pfit.pos,
-                     pipe_config->pch_pfit.size);
+                     pipe_config->pch_pfit.size,
+                     pipe_config->pch_pfit.enabled ? "enabled" : "disabled");
        DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
+       DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide);
 }
 
 static bool check_encoder_cloning(struct drm_crtc *crtc)
@@ -8383,6 +8425,10 @@ intel_modeset_pipe_config(struct drm_crtc *crtc,
 
        drm_mode_copy(&pipe_config->adjusted_mode, mode);
        drm_mode_copy(&pipe_config->requested_mode, mode);
+
+       pipe_config->pipe_src_w = mode->hdisplay;
+       pipe_config->pipe_src_h = mode->vdisplay;
+
        pipe_config->cpu_transcoder =
                (enum transcoder) to_intel_crtc(crtc)->pipe;
        pipe_config->shared_dpll = DPLL_ID_PRIVATE;
@@ -8739,19 +8785,24 @@ intel_pipe_config_compare(struct drm_device *dev,
                                      DRM_MODE_FLAG_NVSYNC);
        }
 
-       PIPE_CONF_CHECK_I(requested_mode.hdisplay);
-       PIPE_CONF_CHECK_I(requested_mode.vdisplay);
+       PIPE_CONF_CHECK_I(pipe_src_w);
+       PIPE_CONF_CHECK_I(pipe_src_h);
 
        PIPE_CONF_CHECK_I(gmch_pfit.control);
        /* pfit ratios are autocomputed by the hw on gen4+ */
        if (INTEL_INFO(dev)->gen < 4)
                PIPE_CONF_CHECK_I(gmch_pfit.pgm_ratios);
        PIPE_CONF_CHECK_I(gmch_pfit.lvds_border_bits);
-       PIPE_CONF_CHECK_I(pch_pfit.pos);
-       PIPE_CONF_CHECK_I(pch_pfit.size);
+       PIPE_CONF_CHECK_I(pch_pfit.enabled);
+       if (current_config->pch_pfit.enabled) {
+               PIPE_CONF_CHECK_I(pch_pfit.pos);
+               PIPE_CONF_CHECK_I(pch_pfit.size);
+       }
 
        PIPE_CONF_CHECK_I(ips_enabled);
 
+       PIPE_CONF_CHECK_I(double_wide);
+
        PIPE_CONF_CHECK_I(shared_dpll);
        PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
        PIPE_CONF_CHECK_X(dpll_hw_state.dpll_md);
@@ -9001,7 +9052,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,
        unsigned disable_pipes, prepare_pipes, modeset_pipes;
        int ret = 0;
 
-       saved_mode = kmalloc(2 * sizeof(*saved_mode), GFP_KERNEL);
+       saved_mode = kcalloc(2, sizeof(*saved_mode), GFP_KERNEL);
        if (!saved_mode)
                return -ENOMEM;
        saved_hwmode = saved_mode + 1;
@@ -9540,7 +9591,7 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
        struct intel_crtc *intel_crtc;
        int i;
 
-       intel_crtc = kzalloc(sizeof(struct intel_crtc) + (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
+       intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
        if (intel_crtc == NULL)
                return;
 
@@ -10139,20 +10190,11 @@ static struct intel_quirk intel_quirks[] = {
        /* Sony Vaio Y cannot use SSC on LVDS */
        { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable },
 
-       /* Acer Aspire 5734Z must invert backlight brightness */
-       { 0x2a42, 0x1025, 0x0459, quirk_invert_brightness },
-
-       /* Acer/eMachines G725 */
-       { 0x2a42, 0x1025, 0x0210, quirk_invert_brightness },
-
-       /* Acer/eMachines e725 */
-       { 0x2a42, 0x1025, 0x0212, quirk_invert_brightness },
-
-       /* Acer/Packard Bell NCL20 */
-       { 0x2a42, 0x1025, 0x034b, quirk_invert_brightness },
-
-       /* Acer Aspire 4736Z */
-       { 0x2a42, 0x1025, 0x0260, quirk_invert_brightness },
+       /*
+        * All GM45 Acer (and its brands eMachines and Packard Bell) laptops
+        * seem to use inverted backlight PWM.
+        */
+       { 0x2a42, 0x1025, PCI_ANY_ID, quirk_invert_brightness },
 
        /* Dell XPS13 HD Sandy Bridge */
        { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable },
@@ -10192,15 +10234,6 @@ static void i915_disable_vga(struct drm_device *dev)
        outb(SR01, VGA_SR_INDEX);
        sr1 = inb(VGA_SR_DATA);
        outb(sr1 | 1<<5, VGA_SR_DATA);
-
-       /* Disable VGA memory on Intel HD */
-       if (HAS_PCH_SPLIT(dev)) {
-               outb(inb(VGA_MSR_READ) & ~VGA_MSR_MEM_EN, VGA_MSR_WRITE);
-               vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO |
-                                                  VGA_RSRC_NORMAL_IO |
-                                                  VGA_RSRC_NORMAL_MEM);
-       }
-
        vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
        udelay(300);
 
@@ -10208,7 +10241,7 @@ static void i915_disable_vga(struct drm_device *dev)
        POSTING_READ(vga_reg);
 }
 
-static void i915_enable_vga(struct drm_device *dev)
+static void i915_enable_vga_mem(struct drm_device *dev)
 {
        /* Enable VGA memory on Intel HD */
        if (HAS_PCH_SPLIT(dev)) {
@@ -10222,10 +10255,21 @@ static void i915_enable_vga(struct drm_device *dev)
        }
 }
 
-void intel_modeset_init_hw(struct drm_device *dev)
+void i915_disable_vga_mem(struct drm_device *dev)
 {
-       intel_init_power_well(dev);
+       /* Disable VGA memory on Intel HD */
+       if (HAS_PCH_SPLIT(dev)) {
+               vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
+               outb(inb(VGA_MSR_READ) & ~VGA_MSR_MEM_EN, VGA_MSR_WRITE);
+               vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO |
+                                                  VGA_RSRC_NORMAL_IO |
+                                                  VGA_RSRC_NORMAL_MEM);
+               vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
+       }
+}
 
+void intel_modeset_init_hw(struct drm_device *dev)
+{
        intel_prepare_ddi(dev);
 
        intel_init_clock_gating(dev);
@@ -10500,6 +10544,7 @@ void i915_redisable_vga(struct drm_device *dev)
        if (I915_READ(vga_reg) != VGA_DISP_DISABLE) {
                DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
                i915_disable_vga(dev);
+               i915_disable_vga_mem(dev);
        }
 }
 
@@ -10591,7 +10636,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        enum pipe pipe;
-       struct drm_plane *plane;
        struct intel_crtc *crtc;
        struct intel_encoder *encoder;
        int i;
@@ -10639,6 +10683,8 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
        }
 
        if (force_restore) {
+               i915_redisable_vga(dev);
+
                /*
                 * We need to use raw interfaces for restoring state to avoid
                 * checking (bogus) intermediate states.
@@ -10650,10 +10696,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
                        __intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y,
                                         crtc->fb);
                }
-               list_for_each_entry(plane, &dev->mode_config.plane_list, head)
-                       intel_plane_restore(plane);
-
-               i915_redisable_vga(dev);
        } else {
                intel_modeset_update_staged_output_state(dev);
        }
@@ -10704,7 +10746,7 @@ void intel_modeset_cleanup(struct drm_device *dev)
 
        intel_disable_fbc(dev);
 
-       i915_enable_vga(dev);
+       i915_enable_vga_mem(dev);
 
        intel_disable_gt_powersave(dev);