Revert "drm/i915: Don't enable pipe/plane/VCO early (wait for DPMS on)."
[safe/jmp/linux-2.6] / drivers / gpu / drm / i915 / intel_display.c
index e38c906..cc8131f 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/input.h>
 #include <linux/i2c.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include "drmP.h"
 #include "intel_drv.h"
 #include "i915_drm.h"
@@ -886,9 +887,9 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
 
        memset(best_clock, 0, sizeof(*best_clock));
        max_n = limit->n.max;
-       /* based on hardware requriment prefer smaller n to precision */
+       /* based on hardware requirement, prefer smaller n to precision */
        for (clock.n = limit->n.min; clock.n <= max_n; clock.n++) {
-               /* based on hardware requirment prefere larger m1,m2 */
+               /* based on hardware requirement, prefere larger m1,m2 */
                for (clock.m1 = limit->m1.max;
                     clock.m1 >= limit->m1.min; clock.m1--) {
                        for (clock.m2 = limit->m2.max;
@@ -1028,28 +1029,36 @@ static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 void i8xx_disable_fbc(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       unsigned long timeout = jiffies + msecs_to_jiffies(1);
        u32 fbc_ctl;
 
        if (!I915_HAS_FBC(dev))
                return;
 
+       if (!(I915_READ(FBC_CONTROL) & FBC_CTL_EN))
+               return; /* Already off, just return */
+
        /* Disable compression */
        fbc_ctl = I915_READ(FBC_CONTROL);
        fbc_ctl &= ~FBC_CTL_EN;
        I915_WRITE(FBC_CONTROL, fbc_ctl);
 
        /* Wait for compressing bit to clear */
-       while (I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING)
-               ; /* nothing */
+       while (I915_READ(FBC_STATUS) & FBC_STAT_COMPRESSING) {
+               if (time_after(jiffies, timeout)) {
+                       DRM_DEBUG_DRIVER("FBC idle timed out\n");
+                       break;
+               }
+               ; /* do nothing */
+       }
 
        intel_wait_for_vblank(dev);
 
        DRM_DEBUG_KMS("disabled FBC\n");
 }
 
-static bool i8xx_fbc_enabled(struct drm_crtc *crtc)
+static bool i8xx_fbc_enabled(struct drm_device *dev)
 {
-       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
@@ -1106,14 +1115,43 @@ void g4x_disable_fbc(struct drm_device *dev)
        DRM_DEBUG_KMS("disabled FBC\n");
 }
 
-static bool g4x_fbc_enabled(struct drm_crtc *crtc)
+static bool g4x_fbc_enabled(struct drm_device *dev)
 {
-       struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
        return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
 }
 
+bool intel_fbc_enabled(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (!dev_priv->display.fbc_enabled)
+               return false;
+
+       return dev_priv->display.fbc_enabled(dev);
+}
+
+void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+{
+       struct drm_i915_private *dev_priv = crtc->dev->dev_private;
+
+       if (!dev_priv->display.enable_fbc)
+               return;
+
+       dev_priv->display.enable_fbc(crtc, interval);
+}
+
+void intel_disable_fbc(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (!dev_priv->display.disable_fbc)
+               return;
+
+       dev_priv->display.disable_fbc(dev);
+}
+
 /**
  * intel_update_fbc - enable/disable FBC as needed
  * @crtc: CRTC to point the compressor at
@@ -1148,9 +1186,7 @@ static void intel_update_fbc(struct drm_crtc *crtc,
        if (!i915_powersave)
                return;
 
-       if (!dev_priv->display.fbc_enabled ||
-           !dev_priv->display.enable_fbc ||
-           !dev_priv->display.disable_fbc)
+       if (!I915_HAS_FBC(dev))
                return;
 
        if (!crtc->fb)
@@ -1197,28 +1233,26 @@ static void intel_update_fbc(struct drm_crtc *crtc,
                goto out_disable;
        }
 
-       if (dev_priv->display.fbc_enabled(crtc)) {
+       if (intel_fbc_enabled(dev)) {
                /* We can re-enable it in this case, but need to update pitch */
-               if (fb->pitch > dev_priv->cfb_pitch)
-                       dev_priv->display.disable_fbc(dev);
-               if (obj_priv->fence_reg != dev_priv->cfb_fence)
-                       dev_priv->display.disable_fbc(dev);
-               if (plane != dev_priv->cfb_plane)
-                       dev_priv->display.disable_fbc(dev);
+               if ((fb->pitch > dev_priv->cfb_pitch) ||
+                   (obj_priv->fence_reg != dev_priv->cfb_fence) ||
+                   (plane != dev_priv->cfb_plane))
+                       intel_disable_fbc(dev);
        }
 
-       if (!dev_priv->display.fbc_enabled(crtc)) {
-               /* Now try to turn it back on if possible */
-               dev_priv->display.enable_fbc(crtc, 500);
-       }
+       /* Now try to turn it back on if possible */
+       if (!intel_fbc_enabled(dev))
+               intel_enable_fbc(crtc, 500);
 
        return;
 
 out_disable:
-       DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
        /* Multiple disables should be harmless */
-       if (dev_priv->display.fbc_enabled(crtc))
-               dev_priv->display.disable_fbc(dev);
+       if (intel_fbc_enabled(dev)) {
+               DRM_DEBUG_KMS("unsupported config, disabling FBC\n");
+               intel_disable_fbc(dev);
+       }
 }
 
 static int
@@ -1362,7 +1396,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
        Start = obj_priv->gtt_offset;
        Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
 
-       DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+       DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n",
+                     Start, Offset, x, y, crtc->fb->pitch);
        I915_WRITE(dspstride, crtc->fb->pitch);
        if (IS_I965G(dev)) {
                I915_WRITE(dspbase, Offset);
@@ -1507,7 +1542,8 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
        /* enable CPU FDI TX and PCH FDI RX */
        temp = I915_READ(fdi_tx_reg);
        temp |= FDI_TX_ENABLE;
-       temp |= FDI_DP_PORT_WIDTH_X4; /* default */
+       temp &= ~(7 << 19);
+       temp |= (intel_crtc->fdi_lanes - 1) << 19;
        temp &= ~FDI_LINK_TRAIN_NONE;
        temp |= FDI_LINK_TRAIN_PATTERN_1;
        I915_WRITE(fdi_tx_reg, temp);
@@ -1607,7 +1643,8 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
        /* enable CPU FDI TX and PCH FDI RX */
        temp = I915_READ(fdi_tx_reg);
        temp |= FDI_TX_ENABLE;
-       temp |= FDI_DP_PORT_WIDTH_X4; /* default */
+       temp &= ~(7 << 19);
+       temp |= (intel_crtc->fdi_lanes - 1) << 19;
        temp &= ~FDI_LINK_TRAIN_NONE;
        temp |= FDI_LINK_TRAIN_PATTERN_1;
        temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
@@ -1769,8 +1806,9 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
                         */
                        temp &= ~(0x7 << 16);
                        temp |= (pipe_bpc << 11);
-                       I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE |
-                                       FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */
+                       temp &= ~(7 << 19);
+                       temp |= (intel_crtc->fdi_lanes - 1) << 19;
+                       I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);
                        I915_READ(fdi_rx_reg);
                        udelay(200);
 
@@ -2318,6 +2356,8 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
                if (mode->clock * 3 > 27000 * 4)
                        return MODE_CLOCK_HIGH;
        }
+
+       drm_mode_set_crtcinfo(adjusted_mode, 0);
        return true;
 }
 
@@ -2527,6 +2567,30 @@ static struct intel_watermark_params i830_wm_info = {
        I830_FIFO_LINE_SIZE
 };
 
+static struct intel_watermark_params ironlake_display_wm_info = {
+       ILK_DISPLAY_FIFO,
+       ILK_DISPLAY_MAXWM,
+       ILK_DISPLAY_DFTWM,
+       2,
+       ILK_FIFO_LINE_SIZE
+};
+
+static struct intel_watermark_params ironlake_display_srwm_info = {
+       ILK_DISPLAY_SR_FIFO,
+       ILK_DISPLAY_MAX_SRWM,
+       ILK_DISPLAY_DFT_SRWM,
+       2,
+       ILK_FIFO_LINE_SIZE
+};
+
+static struct intel_watermark_params ironlake_cursor_srwm_info = {
+       ILK_CURSOR_SR_FIFO,
+       ILK_CURSOR_MAX_SRWM,
+       ILK_CURSOR_DFT_SRWM,
+       2,
+       ILK_FIFO_LINE_SIZE
+};
+
 /**
  * intel_calculate_wm - calculate watermark level
  * @clock_in_khz: pixel clock
@@ -2578,6 +2642,7 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
 
 struct cxsr_latency {
        int is_desktop;
+       int is_ddr3;
        unsigned long fsb_freq;
        unsigned long mem_freq;
        unsigned long display_sr;
@@ -2587,33 +2652,45 @@ struct cxsr_latency {
 };
 
 static struct cxsr_latency cxsr_latency_table[] = {
-       {1, 800, 400, 3382, 33382, 3983, 33983},    /* DDR2-400 SC */
-       {1, 800, 667, 3354, 33354, 3807, 33807},    /* DDR2-667 SC */
-       {1, 800, 800, 3347, 33347, 3763, 33763},    /* DDR2-800 SC */
-
-       {1, 667, 400, 3400, 33400, 4021, 34021},    /* DDR2-400 SC */
-       {1, 667, 667, 3372, 33372, 3845, 33845},    /* DDR2-667 SC */
-       {1, 667, 800, 3386, 33386, 3822, 33822},    /* DDR2-800 SC */
-
-       {1, 400, 400, 3472, 33472, 4173, 34173},    /* DDR2-400 SC */
-       {1, 400, 667, 3443, 33443, 3996, 33996},    /* DDR2-667 SC */
-       {1, 400, 800, 3430, 33430, 3946, 33946},    /* DDR2-800 SC */
-
-       {0, 800, 400, 3438, 33438, 4065, 34065},    /* DDR2-400 SC */
-       {0, 800, 667, 3410, 33410, 3889, 33889},    /* DDR2-667 SC */
-       {0, 800, 800, 3403, 33403, 3845, 33845},    /* DDR2-800 SC */
-
-       {0, 667, 400, 3456, 33456, 4103, 34106},    /* DDR2-400 SC */
-       {0, 667, 667, 3428, 33428, 3927, 33927},    /* DDR2-667 SC */
-       {0, 667, 800, 3443, 33443, 3905, 33905},    /* DDR2-800 SC */
-
-       {0, 400, 400, 3528, 33528, 4255, 34255},    /* DDR2-400 SC */
-       {0, 400, 667, 3500, 33500, 4079, 34079},    /* DDR2-667 SC */
-       {0, 400, 800, 3487, 33487, 4029, 34029},    /* DDR2-800 SC */
+       {1, 0, 800, 400, 3382, 33382, 3983, 33983},    /* DDR2-400 SC */
+       {1, 0, 800, 667, 3354, 33354, 3807, 33807},    /* DDR2-667 SC */
+       {1, 0, 800, 800, 3347, 33347, 3763, 33763},    /* DDR2-800 SC */
+       {1, 1, 800, 667, 6420, 36420, 6873, 36873},    /* DDR3-667 SC */
+       {1, 1, 800, 800, 5902, 35902, 6318, 36318},    /* DDR3-800 SC */
+
+       {1, 0, 667, 400, 3400, 33400, 4021, 34021},    /* DDR2-400 SC */
+       {1, 0, 667, 667, 3372, 33372, 3845, 33845},    /* DDR2-667 SC */
+       {1, 0, 667, 800, 3386, 33386, 3822, 33822},    /* DDR2-800 SC */
+       {1, 1, 667, 667, 6438, 36438, 6911, 36911},    /* DDR3-667 SC */
+       {1, 1, 667, 800, 5941, 35941, 6377, 36377},    /* DDR3-800 SC */
+
+       {1, 0, 400, 400, 3472, 33472, 4173, 34173},    /* DDR2-400 SC */
+       {1, 0, 400, 667, 3443, 33443, 3996, 33996},    /* DDR2-667 SC */
+       {1, 0, 400, 800, 3430, 33430, 3946, 33946},    /* DDR2-800 SC */
+       {1, 1, 400, 667, 6509, 36509, 7062, 37062},    /* DDR3-667 SC */
+       {1, 1, 400, 800, 5985, 35985, 6501, 36501},    /* DDR3-800 SC */
+
+       {0, 0, 800, 400, 3438, 33438, 4065, 34065},    /* DDR2-400 SC */
+       {0, 0, 800, 667, 3410, 33410, 3889, 33889},    /* DDR2-667 SC */
+       {0, 0, 800, 800, 3403, 33403, 3845, 33845},    /* DDR2-800 SC */
+       {0, 1, 800, 667, 6476, 36476, 6955, 36955},    /* DDR3-667 SC */
+       {0, 1, 800, 800, 5958, 35958, 6400, 36400},    /* DDR3-800 SC */
+
+       {0, 0, 667, 400, 3456, 33456, 4103, 34106},    /* DDR2-400 SC */
+       {0, 0, 667, 667, 3428, 33428, 3927, 33927},    /* DDR2-667 SC */
+       {0, 0, 667, 800, 3443, 33443, 3905, 33905},    /* DDR2-800 SC */
+       {0, 1, 667, 667, 6494, 36494, 6993, 36993},    /* DDR3-667 SC */
+       {0, 1, 667, 800, 5998, 35998, 6460, 36460},    /* DDR3-800 SC */
+
+       {0, 0, 400, 400, 3528, 33528, 4255, 34255},    /* DDR2-400 SC */
+       {0, 0, 400, 667, 3500, 33500, 4079, 34079},    /* DDR2-667 SC */
+       {0, 0, 400, 800, 3487, 33487, 4029, 34029},    /* DDR2-800 SC */
+       {0, 1, 400, 667, 6566, 36566, 7145, 37145},    /* DDR3-667 SC */
+       {0, 1, 400, 800, 6042, 36042, 6584, 36584},    /* DDR3-800 SC */
 };
 
-static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb,
-                                                  int mem)
+static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int is_ddr3, 
+                                                  int fsb, int mem)
 {
        int i;
        struct cxsr_latency *latency;
@@ -2624,6 +2701,7 @@ static struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, int fsb,
        for (i = 0; i < ARRAY_SIZE(cxsr_latency_table); i++) {
                latency = &cxsr_latency_table[i];
                if (is_desktop == latency->is_desktop &&
+                   is_ddr3 == latency->is_ddr3 &&
                    fsb == latency->fsb_freq && mem == latency->mem_freq)
                        return latency;
        }
@@ -2738,8 +2816,8 @@ static void pineview_update_wm(struct drm_device *dev,  int planea_clock,
        struct cxsr_latency *latency;
        int sr_clock;
 
-       latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->fsb_freq,
-                                        dev_priv->mem_freq);
+       latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3, 
+                                        dev_priv->fsb_freq, dev_priv->mem_freq);
        if (!latency) {
                DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
                pineview_disable_cxsr(dev);
@@ -3014,6 +3092,108 @@ static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused,
        I915_WRITE(FW_BLC, fwater_lo);
 }
 
+#define ILK_LP0_PLANE_LATENCY          700
+
+static void ironlake_update_wm(struct drm_device *dev,  int planea_clock,
+                      int planeb_clock, int sr_hdisplay, int pixel_size)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
+       int sr_wm, cursor_wm;
+       unsigned long line_time_us;
+       int sr_clock, entries_required;
+       u32 reg_value;
+
+       /* Calculate and update the watermark for plane A */
+       if (planea_clock) {
+               entries_required = ((planea_clock / 1000) * pixel_size *
+                                    ILK_LP0_PLANE_LATENCY) / 1000;
+               entries_required = DIV_ROUND_UP(entries_required,
+                                  ironlake_display_wm_info.cacheline_size);
+               planea_wm = entries_required +
+                           ironlake_display_wm_info.guard_size;
+
+               if (planea_wm > (int)ironlake_display_wm_info.max_wm)
+                       planea_wm = ironlake_display_wm_info.max_wm;
+
+               cursora_wm = 16;
+               reg_value = I915_READ(WM0_PIPEA_ILK);
+               reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
+               reg_value |= (planea_wm << WM0_PIPE_PLANE_SHIFT) |
+                            (cursora_wm & WM0_PIPE_CURSOR_MASK);
+               I915_WRITE(WM0_PIPEA_ILK, reg_value);
+               DRM_DEBUG_KMS("FIFO watermarks For pipe A - plane %d, "
+                               "cursor: %d\n", planea_wm, cursora_wm);
+       }
+       /* Calculate and update the watermark for plane B */
+       if (planeb_clock) {
+               entries_required = ((planeb_clock / 1000) * pixel_size *
+                                    ILK_LP0_PLANE_LATENCY) / 1000;
+               entries_required = DIV_ROUND_UP(entries_required,
+                                  ironlake_display_wm_info.cacheline_size);
+               planeb_wm = entries_required +
+                           ironlake_display_wm_info.guard_size;
+
+               if (planeb_wm > (int)ironlake_display_wm_info.max_wm)
+                       planeb_wm = ironlake_display_wm_info.max_wm;
+
+               cursorb_wm = 16;
+               reg_value = I915_READ(WM0_PIPEB_ILK);
+               reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
+               reg_value |= (planeb_wm << WM0_PIPE_PLANE_SHIFT) |
+                            (cursorb_wm & WM0_PIPE_CURSOR_MASK);
+               I915_WRITE(WM0_PIPEB_ILK, reg_value);
+               DRM_DEBUG_KMS("FIFO watermarks For pipe B - plane %d, "
+                               "cursor: %d\n", planeb_wm, cursorb_wm);
+       }
+
+       /*
+        * Calculate and update the self-refresh watermark only when one
+        * display plane is used.
+        */
+       if (!planea_clock || !planeb_clock) {
+               int line_count;
+               /* Read the self-refresh latency. The unit is 0.5us */
+               int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK;
+
+               sr_clock = planea_clock ? planea_clock : planeb_clock;
+               line_time_us = ((sr_hdisplay * 1000) / sr_clock);
+
+               /* Use ns/us then divide to preserve precision */
+               line_count = ((ilk_sr_latency * 500) / line_time_us + 1000)
+                              / 1000;
+
+               /* calculate the self-refresh watermark for display plane */
+               entries_required = line_count * sr_hdisplay * pixel_size;
+               entries_required = DIV_ROUND_UP(entries_required,
+                                  ironlake_display_srwm_info.cacheline_size);
+               sr_wm = entries_required +
+                       ironlake_display_srwm_info.guard_size;
+
+               /* calculate the self-refresh watermark for display cursor */
+               entries_required = line_count * pixel_size * 64;
+               entries_required = DIV_ROUND_UP(entries_required,
+                                  ironlake_cursor_srwm_info.cacheline_size);
+               cursor_wm = entries_required +
+                           ironlake_cursor_srwm_info.guard_size;
+
+               /* configure watermark and enable self-refresh */
+               reg_value = I915_READ(WM1_LP_ILK);
+               reg_value &= ~(WM1_LP_LATENCY_MASK | WM1_LP_SR_MASK |
+                              WM1_LP_CURSOR_MASK);
+               reg_value |= WM1_LP_SR_EN |
+                            (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) |
+                            (sr_wm << WM1_LP_SR_SHIFT) | cursor_wm;
+
+               I915_WRITE(WM1_LP_ILK, reg_value);
+               DRM_DEBUG_KMS("self-refresh watermark: display plane %d "
+                               "cursor %d\n", sr_wm, cursor_wm);
+
+       } else {
+               /* Turn off self refresh if both pipes are enabled */
+               I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN);
+       }
+}
 /**
  * intel_update_watermarks - update FIFO watermark values based on current modes
  *
@@ -3242,7 +3422,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
        /* FDI link */
        if (HAS_PCH_SPLIT(dev)) {
-               int lane, link_bw, bpp;
+               int lane = 0, link_bw, bpp;
                /* eDP doesn't require FDI link, so just set DP M/N
                   according to current link config */
                if (is_edp) {
@@ -3256,7 +3436,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                                target_clock = mode->clock;
                        else
                                target_clock = adjusted_mode->clock;
-                       lane = 4;
                        link_bw = 270000;
                }
 
@@ -3308,6 +3487,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                        bpp = 24;
                }
 
+               if (!lane) {
+                       /* 
+                        * Account for spread spectrum to avoid
+                        * oversubscribing the link. Max center spread
+                        * is 2.5%; use 5% for safety's sake.
+                        */
+                       u32 bps = target_clock * bpp * 21 / 20;
+                       lane = bps / (link_bw * 8) + 1;
+               }
+
+               intel_crtc->fdi_lanes = lane;
+
                ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);
        }
 
@@ -3462,6 +3653,11 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                        pipeconf &= ~PIPEACONF_DOUBLE_WIDE;
        }
 
+       dspcntr |= DISPLAY_PLANE_ENABLE;
+       pipeconf |= PIPEACONF_ENABLE;
+       dpll |= DPLL_VCO_ENABLE;
+
+
        /* Disable the panel fitter if it was on our pipe */
        if (!HAS_PCH_SPLIT(dev) && intel_panel_fitter_pipe(dev) == pipe)
                I915_WRITE(PFIT_CONTROL, 0);
@@ -3536,14 +3732,16 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                /* set the dithering flag */
                if (IS_I965G(dev)) {
                        if (dev_priv->lvds_dither) {
-                               if (HAS_PCH_SPLIT(dev))
+                               if (HAS_PCH_SPLIT(dev)) {
                                        pipeconf |= PIPE_ENABLE_DITHER;
-                               else
+                                       pipeconf |= PIPE_DITHER_TYPE_ST01;
+                               } else
                                        lvds |= LVDS_ENABLE_DITHER;
                        } else {
-                               if (HAS_PCH_SPLIT(dev))
+                               if (HAS_PCH_SPLIT(dev)) {
                                        pipeconf &= ~PIPE_ENABLE_DITHER;
-                               else
+                                       pipeconf &= ~PIPE_DITHER_TYPE_MASK;
+                               } else
                                        lvds &= ~LVDS_ENABLE_DITHER;
                        }
                }
@@ -3606,6 +3804,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                }
        }
 
+       if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+               pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
+               /* the chip adds 2 halflines automatically */
+               adjusted_mode->crtc_vdisplay -= 1;
+               adjusted_mode->crtc_vtotal -= 1;
+               adjusted_mode->crtc_vblank_start -= 1;
+               adjusted_mode->crtc_vblank_end -= 1;
+               adjusted_mode->crtc_vsync_end -= 1;
+               adjusted_mode->crtc_vsync_start -= 1;
+       } else
+               pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION; /* progressive */
+
        I915_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
                   ((adjusted_mode->crtc_htotal - 1) << 16));
        I915_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
@@ -3768,6 +3978,13 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
                        DRM_ERROR("failed to pin cursor bo\n");
                        goto fail_locked;
                }
+
+               ret = i915_gem_object_set_to_gtt_domain(bo, 0);
+               if (ret) {
+                       DRM_ERROR("failed to move cursor bo into the GTT\n");
+                       goto fail_unpin;
+               }
+
                addr = obj_priv->gtt_offset;
        } else {
                ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
@@ -3811,6 +4028,8 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
        intel_crtc->cursor_bo = bo;
 
        return 0;
+fail_unpin:
+       i915_gem_object_unpin(bo);
 fail_locked:
        mutex_unlock(&dev->struct_mutex);
 fail:
@@ -4270,6 +4489,8 @@ static void intel_idle_update(struct work_struct *work)
 
        mutex_lock(&dev->struct_mutex);
 
+       i915_update_gfx_val(dev_priv);
+
        if (IS_I945G(dev) || IS_I945GM(dev)) {
                DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
                I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
@@ -4398,12 +4619,6 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe)
        spin_lock_irqsave(&dev->event_lock, flags);
        work = intel_crtc->unpin_work;
        if (work == NULL || !work->pending) {
-               if (work && !work->pending) {
-                       obj_priv = to_intel_bo(work->pending_flip_obj);
-                       DRM_DEBUG_DRIVER("flip finish: %p (%d) not pending?\n",
-                                        obj_priv,
-                                        atomic_read(&obj_priv->pending_flip));
-               }
                spin_unlock_irqrestore(&dev->event_lock, flags);
                return;
        }
@@ -4463,14 +4678,11 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        unsigned long flags;
        int pipesrc_reg = (intel_crtc->pipe == 0) ? PIPEASRC : PIPEBSRC;
        int ret, pipesrc;
-       RING_LOCALS;
 
        work = kzalloc(sizeof *work, GFP_KERNEL);
        if (work == NULL)
                return -ENOMEM;
 
-       mutex_lock(&dev->struct_mutex);
-
        work->event = event;
        work->dev = crtc->dev;
        intel_fb = to_intel_framebuffer(crtc->fb);
@@ -4480,10 +4692,10 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        /* We borrow the event spin lock for protecting unpin_work */
        spin_lock_irqsave(&dev->event_lock, flags);
        if (intel_crtc->unpin_work) {
-               DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
                spin_unlock_irqrestore(&dev->event_lock, flags);
                kfree(work);
-               mutex_unlock(&dev->struct_mutex);
+
+               DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
                return -EBUSY;
        }
        intel_crtc->unpin_work = work;
@@ -4492,13 +4704,19 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        intel_fb = to_intel_framebuffer(fb);
        obj = intel_fb->obj;
 
+       mutex_lock(&dev->struct_mutex);
        ret = intel_pin_and_fence_fb_obj(dev, obj);
        if (ret != 0) {
-               DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
-                         to_intel_bo(obj));
-               kfree(work);
-               intel_crtc->unpin_work = NULL;
                mutex_unlock(&dev->struct_mutex);
+
+               spin_lock_irqsave(&dev->event_lock, flags);
+               intel_crtc->unpin_work = NULL;
+               spin_unlock_irqrestore(&dev->event_lock, flags);
+
+               kfree(work);
+
+               DRM_DEBUG_DRIVER("flip queue: %p pin & fence failed\n",
+                                to_intel_bo(obj));
                return ret;
        }
 
@@ -4748,10 +4966,6 @@ static void intel_setup_outputs(struct drm_device *dev)
 static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb)
 {
        struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-       struct drm_device *dev = fb->dev;
-
-       if (fb->fbdev)
-               intelfb_remove(dev, fb);
 
        drm_framebuffer_cleanup(fb);
        drm_gem_object_unreference_unlocked(intel_fb->obj);
@@ -4774,18 +4988,13 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = {
        .create_handle = intel_user_framebuffer_create_handle,
 };
 
-int intel_framebuffer_create(struct drm_device *dev,
-                            struct drm_mode_fb_cmd *mode_cmd,
-                            struct drm_framebuffer **fb,
-                            struct drm_gem_object *obj)
+int intel_framebuffer_init(struct drm_device *dev,
+                          struct intel_framebuffer *intel_fb,
+                          struct drm_mode_fb_cmd *mode_cmd,
+                          struct drm_gem_object *obj)
 {
-       struct intel_framebuffer *intel_fb;
        int ret;
 
-       intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
-       if (!intel_fb)
-               return -ENOMEM;
-
        ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
        if (ret) {
                DRM_ERROR("framebuffer init failed %d\n", ret);
@@ -4793,40 +5002,41 @@ int intel_framebuffer_create(struct drm_device *dev,
        }
 
        drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
-
        intel_fb->obj = obj;
-
-       *fb = &intel_fb->base;
-
        return 0;
 }
 
-
 static struct drm_framebuffer *
 intel_user_framebuffer_create(struct drm_device *dev,
                              struct drm_file *filp,
                              struct drm_mode_fb_cmd *mode_cmd)
 {
        struct drm_gem_object *obj;
-       struct drm_framebuffer *fb;
+       struct intel_framebuffer *intel_fb;
        int ret;
 
        obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle);
        if (!obj)
                return NULL;
 
-       ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj);
+       intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
+       if (!intel_fb)
+               return NULL;
+
+       ret = intel_framebuffer_init(dev, intel_fb,
+                                    mode_cmd, obj);
        if (ret) {
                drm_gem_object_unreference_unlocked(obj);
+               kfree(intel_fb);
                return NULL;
        }
 
-       return fb;
+       return &intel_fb->base;
 }
 
 static const struct drm_mode_config_funcs intel_mode_funcs = {
        .fb_create = intel_user_framebuffer_create,
-       .fb_changed = intelfb_probe,
+       .output_poll_changed = intel_fb_output_poll_changed,
 };
 
 static struct drm_gem_object *
@@ -4835,7 +5045,7 @@ intel_alloc_power_context(struct drm_device *dev)
        struct drm_gem_object *pwrctx;
        int ret;
 
-       pwrctx = drm_gem_object_alloc(dev, 4096);
+       pwrctx = i915_gem_alloc_object(dev, 4096);
        if (!pwrctx) {
                DRM_DEBUG("failed to alloc power context, RC6 disabled\n");
                return NULL;
@@ -4865,10 +5075,32 @@ err_unref:
        return NULL;
 }
 
+bool ironlake_set_drps(struct drm_device *dev, u8 val)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u16 rgvswctl;
+
+       rgvswctl = I915_READ16(MEMSWCTL);
+       if (rgvswctl & MEMCTL_CMD_STS) {
+               DRM_DEBUG("gpu busy, RCS change rejected\n");
+               return false; /* still busy with another command */
+       }
+
+       rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
+               (val << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
+       I915_WRITE16(MEMSWCTL, rgvswctl);
+       POSTING_READ16(MEMSWCTL);
+
+       rgvswctl |= MEMCTL_CMD_STS;
+       I915_WRITE16(MEMSWCTL, rgvswctl);
+
+       return true;
+}
+
 void ironlake_enable_drps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 rgvmodectl = I915_READ(MEMMODECTL), rgvswctl;
+       u32 rgvmodectl = I915_READ(MEMMODECTL);
        u8 fmax, fmin, fstart, vstart;
        int i = 0;
 
@@ -4887,13 +5119,21 @@ void ironlake_enable_drps(struct drm_device *dev)
        fmin = (rgvmodectl & MEMMODE_FMIN_MASK);
        fstart = (rgvmodectl & MEMMODE_FSTART_MASK) >>
                MEMMODE_FSTART_SHIFT;
+       fstart = fmax;
+
        vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >>
                PXVFREQ_PX_SHIFT;
 
-       dev_priv->max_delay = fstart; /* can't go to fmax w/o IPS */
+       dev_priv->fmax = fstart; /* IPS callback will increase this */
+       dev_priv->fstart = fstart;
+
+       dev_priv->max_delay = fmax;
        dev_priv->min_delay = fmin;
        dev_priv->cur_delay = fstart;
 
+       DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n", fmax, fmin,
+                        fstart);
+
        I915_WRITE(MEMINTREN, MEMINT_CX_SUPR_EN | MEMINT_EVAL_CHG_EN);
 
        /*
@@ -4915,20 +5155,19 @@ void ironlake_enable_drps(struct drm_device *dev)
        }
        msleep(1);
 
-       rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
-               (fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
-       I915_WRITE(MEMSWCTL, rgvswctl);
-       POSTING_READ(MEMSWCTL);
+       ironlake_set_drps(dev, fstart);
 
-       rgvswctl |= MEMCTL_CMD_STS;
-       I915_WRITE(MEMSWCTL, rgvswctl);
+       dev_priv->last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) +
+               I915_READ(0x112e0);
+       dev_priv->last_time1 = jiffies_to_msecs(jiffies);
+       dev_priv->last_count2 = I915_READ(0x112f4);
+       getrawmonotonic(&dev_priv->last_time2);
 }
 
 void ironlake_disable_drps(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 rgvswctl;
-       u8 fstart;
+       u16 rgvswctl = I915_READ16(MEMSWCTL);
 
        /* Ack interrupts, disable EFC interrupt */
        I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
@@ -4938,11 +5177,7 @@ void ironlake_disable_drps(struct drm_device *dev)
        I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT);
 
        /* Go back to the starting frequency */
-       fstart = (I915_READ(MEMMODECTL) & MEMMODE_FSTART_MASK) >>
-               MEMMODE_FSTART_SHIFT;
-       rgvswctl = (MEMCTL_CMD_CHFREQ << MEMCTL_CMD_SHIFT) |
-               (fstart << MEMCTL_FREQ_SHIFT) | MEMCTL_SFCAVM;
-       I915_WRITE(MEMSWCTL, rgvswctl);
+       ironlake_set_drps(dev, dev_priv->fstart);
        msleep(1);
        rgvswctl |= MEMCTL_CMD_STS;
        I915_WRITE(MEMSWCTL, rgvswctl);
@@ -4950,6 +5185,92 @@ void ironlake_disable_drps(struct drm_device *dev)
 
 }
 
+static unsigned long intel_pxfreq(u32 vidfreq)
+{
+       unsigned long freq;
+       int div = (vidfreq & 0x3f0000) >> 16;
+       int post = (vidfreq & 0x3000) >> 12;
+       int pre = (vidfreq & 0x7);
+
+       if (!pre)
+               return 0;
+
+       freq = ((div * 133333) / ((1<<post) * pre));
+
+       return freq;
+}
+
+void intel_init_emon(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       u32 lcfuse;
+       u8 pxw[16];
+       int i;
+
+       /* Disable to program */
+       I915_WRITE(ECR, 0);
+       POSTING_READ(ECR);
+
+       /* Program energy weights for various events */
+       I915_WRITE(SDEW, 0x15040d00);
+       I915_WRITE(CSIEW0, 0x007f0000);
+       I915_WRITE(CSIEW1, 0x1e220004);
+       I915_WRITE(CSIEW2, 0x04000004);
+
+       for (i = 0; i < 5; i++)
+               I915_WRITE(PEW + (i * 4), 0);
+       for (i = 0; i < 3; i++)
+               I915_WRITE(DEW + (i * 4), 0);
+
+       /* Program P-state weights to account for frequency power adjustment */
+       for (i = 0; i < 16; i++) {
+               u32 pxvidfreq = I915_READ(PXVFREQ_BASE + (i * 4));
+               unsigned long freq = intel_pxfreq(pxvidfreq);
+               unsigned long vid = (pxvidfreq & PXVFREQ_PX_MASK) >>
+                       PXVFREQ_PX_SHIFT;
+               unsigned long val;
+
+               val = vid * vid;
+               val *= (freq / 1000);
+               val *= 255;
+               val /= (127*127*900);
+               if (val > 0xff)
+                       DRM_ERROR("bad pxval: %ld\n", val);
+               pxw[i] = val;
+       }
+       /* Render standby states get 0 weight */
+       pxw[14] = 0;
+       pxw[15] = 0;
+
+       for (i = 0; i < 4; i++) {
+               u32 val = (pxw[i*4] << 24) | (pxw[(i*4)+1] << 16) |
+                       (pxw[(i*4)+2] << 8) | (pxw[(i*4)+3]);
+               I915_WRITE(PXW + (i * 4), val);
+       }
+
+       /* Adjust magic regs to magic values (more experimental results) */
+       I915_WRITE(OGW0, 0);
+       I915_WRITE(OGW1, 0);
+       I915_WRITE(EG0, 0x00007f00);
+       I915_WRITE(EG1, 0x0000000e);
+       I915_WRITE(EG2, 0x000e0000);
+       I915_WRITE(EG3, 0x68000300);
+       I915_WRITE(EG4, 0x42000000);
+       I915_WRITE(EG5, 0x00140031);
+       I915_WRITE(EG6, 0);
+       I915_WRITE(EG7, 0);
+
+       for (i = 0; i < 8; i++)
+               I915_WRITE(PXWL + (i * 4), 0);
+
+       /* Enable PMON + select events */
+       I915_WRITE(ECR, 0x80000019);
+
+       lcfuse = I915_READ(LCFUSE02);
+
+       dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
+}
+
 void intel_init_clock_gating(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4973,6 +5294,25 @@ void intel_init_clock_gating(struct drm_device *dev)
                }
 
                I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
+
+               /*
+                * According to the spec the following bits should be set in
+                * order to enable memory self-refresh
+                * The bit 22/21 of 0x42004
+                * The bit 5 of 0x42020
+                * The bit 15 of 0x45000
+                */
+               if (IS_IRONLAKE(dev)) {
+                       I915_WRITE(ILK_DISPLAY_CHICKEN2,
+                                       (I915_READ(ILK_DISPLAY_CHICKEN2) |
+                                       ILK_DPARB_GATE | ILK_VSDPFD_FULL));
+                       I915_WRITE(ILK_DSPCLK_GATE,
+                                       (I915_READ(ILK_DSPCLK_GATE) |
+                                               ILK_DPARB_CLK_GATE));
+                       I915_WRITE(DISP_ARB_CTL,
+                                       (I915_READ(DISP_ARB_CTL) |
+                                               DISP_FBC_WM_DIS));
+               }
                return;
        } else if (IS_G4X(dev)) {
                uint32_t dspclk_gate;
@@ -5050,8 +5390,7 @@ static void intel_init_display(struct drm_device *dev)
        else
                dev_priv->display.dpms = i9xx_crtc_dpms;
 
-       /* Only mobile has FBC, leave pointers NULL for other chips */
-       if (IS_MOBILE(dev)) {
+       if (I915_HAS_FBC(dev)) {
                if (IS_GM45(dev)) {
                        dev_priv->display.fbc_enabled = g4x_fbc_enabled;
                        dev_priv->display.enable_fbc = g4x_enable_fbc;
@@ -5088,15 +5427,26 @@ static void intel_init_display(struct drm_device *dev)
                        i830_get_display_clock_speed;
 
        /* For FIFO watermark updates */
-       if (HAS_PCH_SPLIT(dev))
-               dev_priv->display.update_wm = NULL;
-       else if (IS_PINEVIEW(dev)) {
+       if (HAS_PCH_SPLIT(dev)) {
+               if (IS_IRONLAKE(dev)) {
+                       if (I915_READ(MLTR_ILK) & ILK_SRLT_MASK)
+                               dev_priv->display.update_wm = ironlake_update_wm;
+                       else {
+                               DRM_DEBUG_KMS("Failed to get proper latency. "
+                                             "Disable CxSR\n");
+                               dev_priv->display.update_wm = NULL;
+                       }
+               } else
+                       dev_priv->display.update_wm = NULL;
+       } else if (IS_PINEVIEW(dev)) {
                if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
+                                           dev_priv->is_ddr3,
                                            dev_priv->fsb_freq,
                                            dev_priv->mem_freq)) {
                        DRM_INFO("failed to find known CxSR latency "
-                                "(found fsb freq %d, mem freq %d), "
+                                "(found ddr%s fsb freq %d, mem freq %d), "
                                 "disabling CxSR\n",
+                                (dev_priv->is_ddr3 == 1) ? "3": "2",
                                 dev_priv->fsb_freq, dev_priv->mem_freq);
                        /* Disable CxSR and never update its watermark again */
                        pineview_disable_cxsr(dev);
@@ -5107,24 +5457,24 @@ static void intel_init_display(struct drm_device *dev)
                dev_priv->display.update_wm = g4x_update_wm;
        else if (IS_I965G(dev))
                dev_priv->display.update_wm = i965_update_wm;
-       else if (IS_I9XX(dev) || IS_MOBILE(dev)) {
+       else if (IS_I9XX(dev)) {
                dev_priv->display.update_wm = i9xx_update_wm;
                dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
+       } else if (IS_I85X(dev)) {
+               dev_priv->display.update_wm = i9xx_update_wm;
+               dev_priv->display.get_fifo_size = i85x_get_fifo_size;
        } else {
-               if (IS_I85X(dev))
-                       dev_priv->display.get_fifo_size = i85x_get_fifo_size;
-               else if (IS_845G(dev))
+               dev_priv->display.update_wm = i830_update_wm;
+               if (IS_845G(dev))
                        dev_priv->display.get_fifo_size = i845_get_fifo_size;
                else
                        dev_priv->display.get_fifo_size = i830_get_fifo_size;
-               dev_priv->display.update_wm = i830_update_wm;
        }
 }
 
 void intel_modeset_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int num_pipe;
        int i;
 
        drm_mode_config_init(dev);
@@ -5154,13 +5504,13 @@ void intel_modeset_init(struct drm_device *dev)
                dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0);
 
        if (IS_MOBILE(dev) || IS_I9XX(dev))
-               num_pipe = 2;
+               dev_priv->num_pipe = 2;
        else
-               num_pipe = 1;
+               dev_priv->num_pipe = 1;
        DRM_DEBUG_KMS("%d display pipe%s available.\n",
-                 num_pipe, num_pipe > 1 ? "s" : "");
+                     dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : "");
 
-       for (i = 0; i < num_pipe; i++) {
+       for (i = 0; i < dev_priv->num_pipe; i++) {
                intel_crtc_init(dev, i);
        }
 
@@ -5168,8 +5518,10 @@ void intel_modeset_init(struct drm_device *dev)
 
        intel_init_clock_gating(dev);
 
-       if (IS_IRONLAKE_M(dev))
+       if (IS_IRONLAKE_M(dev)) {
                ironlake_enable_drps(dev);
+               intel_init_emon(dev);
+       }
 
        INIT_WORK(&dev_priv->idle_work, intel_idle_update);
        setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
@@ -5186,6 +5538,9 @@ void intel_modeset_cleanup(struct drm_device *dev)
 
        mutex_lock(&dev->struct_mutex);
 
+       drm_kms_helper_poll_fini(dev);
+       intel_fbdev_fini(dev);
+
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                /* Skip inactive CRTCs */
                if (!crtc->fb)