drm/i915: Re-enable self-refresh
[pandora-kernel.git] / drivers / gpu / drm / i915 / intel_display.c
index 5e47833..49c0723 100644 (file)
@@ -1516,9 +1516,10 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
 
        reg = PIPECONF(pipe);
        val = I915_READ(reg);
-       val |= PIPECONF_ENABLE;
-       I915_WRITE(reg, val);
-       POSTING_READ(reg);
+       if (val & PIPECONF_ENABLE)
+               return;
+
+       I915_WRITE(reg, val | PIPECONF_ENABLE);
        intel_wait_for_vblank(dev_priv->dev, pipe);
 }
 
@@ -1552,9 +1553,10 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv,
 
        reg = PIPECONF(pipe);
        val = I915_READ(reg);
-       val &= ~PIPECONF_ENABLE;
-       I915_WRITE(reg, val);
-       POSTING_READ(reg);
+       if ((val & PIPECONF_ENABLE) == 0)
+               return;
+
+       I915_WRITE(reg, val & ~PIPECONF_ENABLE);
        intel_wait_for_pipe_off(dev_priv->dev, pipe);
 }
 
@@ -1577,9 +1579,10 @@ static void intel_enable_plane(struct drm_i915_private *dev_priv,
 
        reg = DSPCNTR(plane);
        val = I915_READ(reg);
-       val |= DISPLAY_PLANE_ENABLE;
-       I915_WRITE(reg, val);
-       POSTING_READ(reg);
+       if (val & DISPLAY_PLANE_ENABLE)
+               return;
+
+       I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
        intel_wait_for_vblank(dev_priv->dev, pipe);
 }
 
@@ -1610,9 +1613,10 @@ static void intel_disable_plane(struct drm_i915_private *dev_priv,
 
        reg = DSPCNTR(plane);
        val = I915_READ(reg);
-       val &= ~DISPLAY_PLANE_ENABLE;
-       I915_WRITE(reg, val);
-       POSTING_READ(reg);
+       if ((val & DISPLAY_PLANE_ENABLE) == 0)
+               return;
+
+       I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
        intel_flush_display_plane(dev_priv, plane);
        intel_wait_for_vblank(dev_priv->dev, pipe);
 }
@@ -1769,7 +1773,6 @@ static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
                        return;
 
                I915_WRITE(DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN);
-               POSTING_READ(DPFC_CONTROL);
                intel_wait_for_vblank(dev, intel_crtc->pipe);
        }
 
@@ -1825,7 +1828,7 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev)
        u32 blt_ecoskpd;
 
        /* Make sure blitter notifies FBC of writes */
-       __gen6_force_wake_get(dev_priv);
+       __gen6_gt_force_wake_get(dev_priv);
        blt_ecoskpd = I915_READ(GEN6_BLITTER_ECOSKPD);
        blt_ecoskpd |= GEN6_BLITTER_FBC_NOTIFY <<
                GEN6_BLITTER_LOCK_SHIFT;
@@ -1836,7 +1839,7 @@ static void sandybridge_blit_fbc_update(struct drm_device *dev)
                         GEN6_BLITTER_LOCK_SHIFT);
        I915_WRITE(GEN6_BLITTER_ECOSKPD, blt_ecoskpd);
        POSTING_READ(GEN6_BLITTER_ECOSKPD);
-       __gen6_force_wake_put(dev_priv);
+       __gen6_gt_force_wake_put(dev_priv);
 }
 
 static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
@@ -1861,7 +1864,6 @@ static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
                        return;
 
                I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN);
-               POSTING_READ(ILK_DPFC_CONTROL);
                intel_wait_for_vblank(dev, intel_crtc->pipe);
        }
 
@@ -2067,6 +2069,7 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
                           struct drm_i915_gem_object *obj,
                           struct intel_ring_buffer *pipelined)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
        u32 alignment;
        int ret;
 
@@ -2091,9 +2094,10 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
                BUG();
        }
 
+       dev_priv->mm.interruptible = false;
        ret = i915_gem_object_pin(obj, alignment, true);
        if (ret)
-               return ret;
+               goto err_interruptible;
 
        ret = i915_gem_object_set_to_display_plane(obj, pipelined);
        if (ret)
@@ -2105,15 +2109,18 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
         * a fence as the cost is not that onerous.
         */
        if (obj->tiling_mode != I915_TILING_NONE) {
-               ret = i915_gem_object_get_fence(obj, pipelined, false);
+               ret = i915_gem_object_get_fence(obj, pipelined);
                if (ret)
                        goto err_unpin;
        }
 
+       dev_priv->mm.interruptible = true;
        return 0;
 
 err_unpin:
        i915_gem_object_unpin(obj);
+err_interruptible:
+       dev_priv->mm.interruptible = true;
        return ret;
 }
 
@@ -2247,7 +2254,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
                 * This should only fail upon a hung GPU, in which case we
                 * can safely continue.
                 */
-               ret = i915_gem_object_flush_gpu(obj, false);
+               ret = i915_gem_object_flush_gpu(obj);
                (void) ret;
        }
 
@@ -2994,9 +3001,12 @@ static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
 {
        if (!enable && intel_crtc->overlay) {
                struct drm_device *dev = intel_crtc->base.dev;
+               struct drm_i915_private *dev_priv = dev->dev_private;
 
                mutex_lock(&dev->struct_mutex);
-               (void) intel_overlay_switch_off(intel_crtc->overlay, false);
+               dev_priv->mm.interruptible = false;
+               (void) intel_overlay_switch_off(intel_crtc->overlay);
+               dev_priv->mm.interruptible = true;
                mutex_unlock(&dev->struct_mutex);
        }
 
@@ -3875,10 +3885,7 @@ static bool g4x_compute_srwm(struct drm_device *dev,
                              display, cursor);
 }
 
-static inline bool single_plane_enabled(unsigned int mask)
-{
-       return mask && (mask & -mask) == 0;
-}
+#define single_plane_enabled(mask) is_power_of_2(mask)
 
 static void g4x_update_wm(struct drm_device *dev)
 {
@@ -4506,81 +4513,6 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
        return dev_priv->lvds_use_ssc && i915_panel_use_ssc;
 }
 
-static void intel_update_dref(struct drm_i915_private *dev_priv)
-{
-       struct drm_device *dev = dev_priv->dev;
-       struct drm_mode_config *mode_config = &dev->mode_config;
-       struct intel_encoder *encoder;
-       struct drm_crtc *crtc;
-       u32 temp;
-       bool lvds_on = false, edp_on = false, pch_edp_on = false, other_on = false;
-
-       list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {
-               crtc = encoder->base.crtc;
-
-               if (!crtc || !crtc->enabled)
-                       continue;
-
-               switch (encoder->type) {
-               case INTEL_OUTPUT_LVDS:
-                       lvds_on = true;
-                       break;
-               case INTEL_OUTPUT_EDP:
-                       edp_on = true;
-                       if (!pch_edp_on)
-                               pch_edp_on = intel_encoder_is_pch_edp(&encoder->base);
-                       break;
-               default:
-                       other_on = true;
-                       break;
-               }
-       }
-
-       /*XXX BIOS treats 16:31 as a mask for 0:15 */
-
-       temp = I915_READ(PCH_DREF_CONTROL);
-
-       /* First clear the current state for output switching */
-       temp &= ~DREF_SSC1_ENABLE;
-       temp &= ~DREF_SSC4_ENABLE;
-       temp &= ~DREF_SUPERSPREAD_SOURCE_MASK;
-       temp &= ~DREF_NONSPREAD_SOURCE_MASK;
-       temp &= ~DREF_SSC_SOURCE_MASK;
-       temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
-       I915_WRITE(PCH_DREF_CONTROL, temp);
-
-       POSTING_READ(PCH_DREF_CONTROL);
-       udelay(200);
-
-       if ((lvds_on || edp_on) && intel_panel_use_ssc(dev_priv)) {
-               temp |= DREF_SSC_SOURCE_ENABLE;
-               if (edp_on) {
-                       if (!pch_edp_on) {
-                               /* Enable CPU source on CPU attached eDP */
-                               temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
-                       } else {
-                               /* Enable SSC on PCH eDP if needed */
-                               temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
-                       }
-                       I915_WRITE(PCH_DREF_CONTROL, temp);
-               }
-               if (!dev_priv->display_clock_mode)
-                       temp |= DREF_SSC1_ENABLE;
-       }
-
-       if (other_on && dev_priv->display_clock_mode)
-               temp |= DREF_NONSPREAD_CK505_ENABLE;
-       else if (other_on) {
-               temp |= DREF_NONSPREAD_SOURCE_ENABLE;
-               if (edp_on && !pch_edp_on)
-                       temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
-       }
-
-       I915_WRITE(PCH_DREF_CONTROL, temp);
-       POSTING_READ(PCH_DREF_CONTROL);
-       udelay(200);
-}
-
 static int intel_crtc_mode_set(struct drm_crtc *crtc,
                               struct drm_display_mode *mode,
                               struct drm_display_mode *adjusted_mode,
@@ -4806,8 +4738,46 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
         * PCH B stepping, previous chipset stepping should be
         * ignoring this setting.
         */
-       if (HAS_PCH_SPLIT(dev))
-               intel_update_dref(dev_priv);
+       if (HAS_PCH_SPLIT(dev)) {
+               temp = I915_READ(PCH_DREF_CONTROL);
+               /* Always enable nonspread source */
+               temp &= ~DREF_NONSPREAD_SOURCE_MASK;
+               temp |= DREF_NONSPREAD_SOURCE_ENABLE;
+               temp &= ~DREF_SSC_SOURCE_MASK;
+               temp |= DREF_SSC_SOURCE_ENABLE;
+               I915_WRITE(PCH_DREF_CONTROL, temp);
+
+               POSTING_READ(PCH_DREF_CONTROL);
+               udelay(200);
+
+               if (has_edp_encoder) {
+                       if (intel_panel_use_ssc(dev_priv)) {
+                               temp |= DREF_SSC1_ENABLE;
+                               I915_WRITE(PCH_DREF_CONTROL, temp);
+
+                               POSTING_READ(PCH_DREF_CONTROL);
+                               udelay(200);
+                       }
+                       temp &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
+
+                       /* Enable CPU source on CPU attached eDP */
+                       if (!intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
+                               if (intel_panel_use_ssc(dev_priv))
+                                       temp |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD;
+                               else
+                                       temp |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
+                       } else {
+                               /* Enable SSC on PCH eDP if needed */
+                               if (intel_panel_use_ssc(dev_priv)) {
+                                       DRM_ERROR("enabling SSC on PCH\n");
+                                       temp |= DREF_SUPERSPREAD_SOURCE_ENABLE;
+                               }
+                       }
+                       I915_WRITE(PCH_DREF_CONTROL, temp);
+                       POSTING_READ(PCH_DREF_CONTROL);
+                       udelay(200);
+               }
+       }
 
        if (IS_PINEVIEW(dev)) {
                fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2;
@@ -5257,7 +5227,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
        bool visible = base != 0;
 
        if (intel_crtc->cursor_visible != visible) {
-               uint32_t cntl = CURCNTR(pipe);
+               uint32_t cntl = I915_READ(CURCNTR(pipe));
                if (base) {
                        cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
                        cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
@@ -5361,7 +5331,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
        }
 
        obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
-       if (!obj)
+       if (&obj->base == NULL)
                return -ENOENT;
 
        if (obj->base.size < width * height * 4) {
@@ -5627,7 +5597,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       u32 dpll = DPLL(pipe);
+       u32 dpll = I915_READ(DPLL(pipe));
        u32 fp;
        intel_clock_t clock;
 
@@ -5712,13 +5682,14 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
 struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
                                             struct drm_crtc *crtc)
 {
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
        struct drm_display_mode *mode;
-       int htot = HTOTAL(pipe);
-       int hsync = HSYNC(pipe);
-       int vtot = VTOTAL(pipe);
-       int vsync = VSYNC(pipe);
+       int htot = I915_READ(HTOTAL(pipe));
+       int hsync = I915_READ(HSYNC(pipe));
+       int vtot = I915_READ(VTOTAL(pipe));
+       int vsync = I915_READ(VSYNC(pipe));
 
        mode = kzalloc(sizeof(*mode), GFP_KERNEL);
        if (!mode)
@@ -5805,7 +5776,6 @@ static void intel_increase_pllclock(struct drm_crtc *crtc)
 
                dpll &= ~DISPLAY_RATE_SELECT_FPA1;
                I915_WRITE(dpll_reg, dpll);
-               POSTING_READ(dpll_reg);
                intel_wait_for_vblank(dev, pipe);
 
                dpll = I915_READ(dpll_reg);
@@ -5849,7 +5819,6 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)
 
                dpll |= DISPLAY_RATE_SELECT_FPA1;
                I915_WRITE(dpll_reg, dpll);
-               dpll = I915_READ(dpll_reg);
                intel_wait_for_vblank(dev, pipe);
                dpll = I915_READ(dpll_reg);
                if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
@@ -6599,7 +6568,7 @@ intel_user_framebuffer_create(struct drm_device *dev,
        int ret;
 
        obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle));
-       if (!obj)
+       if (&obj->base == NULL)
                return ERR_PTR(-ENOENT);
 
        intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
@@ -6884,7 +6853,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
         * userspace...
         */
        I915_WRITE(GEN6_RC_STATE, 0);
-       __gen6_force_wake_get(dev_priv);
+       __gen6_gt_force_wake_get(dev_priv);
 
        /* disable the counters and set deterministic thresholds */
        I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -6982,7 +6951,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
        /* enable all PM interrupts */
        I915_WRITE(GEN6_PMINTRMSK, 0);
 
-       __gen6_force_wake_put(dev_priv);
+       __gen6_gt_force_wake_put(dev_priv);
 }
 
 void intel_enable_clock_gating(struct drm_device *dev)
@@ -7176,7 +7145,7 @@ static void ironlake_disable_rc6(struct drm_device *dev)
                POSTING_READ(RSTDBYCTL);
        }
 
-       ironlake_disable_rc6(dev);
+       ironlake_teardown_rc6(dev);
 }
 
 static int ironlake_setup_rc6(struct drm_device *dev)