Merge tag 'mmc-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
[cascardo/linux.git] / drivers / gpu / drm / i915 / intel_fbc.c
index 3836a1c..faa6762 100644 (file)
@@ -190,9 +190,13 @@ static void g4x_fbc_activate(struct drm_i915_private *dev_priv)
                dpfc_ctl |= DPFC_CTL_LIMIT_2X;
        else
                dpfc_ctl |= DPFC_CTL_LIMIT_1X;
-       dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fb.fence_reg;
 
-       I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
+       if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
+               dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fb.fence_reg;
+               I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
+       } else {
+               I915_WRITE(DPFC_FENCE_YOFF, 0);
+       }
 
        /* enable it... */
        I915_WRITE(DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
@@ -244,21 +248,29 @@ static void ilk_fbc_activate(struct drm_i915_private *dev_priv)
                dpfc_ctl |= DPFC_CTL_LIMIT_1X;
                break;
        }
-       dpfc_ctl |= DPFC_CTL_FENCE_EN;
-       if (IS_GEN5(dev_priv))
-               dpfc_ctl |= params->fb.fence_reg;
+
+       if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
+               dpfc_ctl |= DPFC_CTL_FENCE_EN;
+               if (IS_GEN5(dev_priv))
+                       dpfc_ctl |= params->fb.fence_reg;
+               if (IS_GEN6(dev_priv)) {
+                       I915_WRITE(SNB_DPFC_CTL_SA,
+                                  SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
+                       I915_WRITE(DPFC_CPU_FENCE_OFFSET,
+                                  params->crtc.fence_y_offset);
+               }
+       } else {
+               if (IS_GEN6(dev_priv)) {
+                       I915_WRITE(SNB_DPFC_CTL_SA, 0);
+                       I915_WRITE(DPFC_CPU_FENCE_OFFSET, 0);
+               }
+       }
 
        I915_WRITE(ILK_DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
        I915_WRITE(ILK_FBC_RT_BASE, params->fb.ggtt_offset | ILK_FBC_RT_VALID);
        /* enable it... */
        I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
 
-       if (IS_GEN6(dev_priv)) {
-               I915_WRITE(SNB_DPFC_CTL_SA,
-                          SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
-               I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset);
-       }
-
        intel_fbc_recompress(dev_priv);
 }
 
@@ -305,7 +317,15 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
                break;
        }
 
-       dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
+       if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
+               dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
+               I915_WRITE(SNB_DPFC_CTL_SA,
+                          SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
+               I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset);
+       } else {
+               I915_WRITE(SNB_DPFC_CTL_SA,0);
+               I915_WRITE(DPFC_CPU_FENCE_OFFSET, 0);
+       }
 
        if (dev_priv->fbc.false_color)
                dpfc_ctl |= FBC_CTL_FALSE_COLOR;
@@ -324,10 +344,6 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
 
        I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
 
-       I915_WRITE(SNB_DPFC_CTL_SA,
-                  SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
-       I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset);
-
        intel_fbc_recompress(dev_priv);
 }
 
@@ -494,7 +510,7 @@ static bool multiple_pipes_ok(struct intel_crtc *crtc,
        if (!no_fbc_on_multiple_pipes(dev_priv))
                return true;
 
-       if (plane_state->visible)
+       if (plane_state->base.visible)
                fbc->visible_pipes_mask |= (1 << pipe);
        else
                fbc->visible_pipes_mask &= ~(1 << pipe);
@@ -709,6 +725,14 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
        return effective_w <= max_w && effective_h <= max_h;
 }
 
+/* XXX replace me when we have VMA tracking for intel_plane_state */
+static int get_fence_id(struct drm_framebuffer *fb)
+{
+       struct i915_vma *vma = i915_gem_object_to_ggtt(intel_fb_obj(fb), NULL);
+
+       return vma && vma->fence ? vma->fence->id : I915_FENCE_REG_NONE;
+}
+
 static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
                                         struct intel_crtc_state *crtc_state,
                                         struct intel_plane_state *plane_state)
@@ -725,9 +749,9 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
                        ilk_pipe_pixel_rate(crtc_state);
 
        cache->plane.rotation = plane_state->base.rotation;
-       cache->plane.src_w = drm_rect_width(&plane_state->src) >> 16;
-       cache->plane.src_h = drm_rect_height(&plane_state->src) >> 16;
-       cache->plane.visible = plane_state->visible;
+       cache->plane.src_w = drm_rect_width(&plane_state->base.src) >> 16;
+       cache->plane.src_h = drm_rect_height(&plane_state->base.src) >> 16;
+       cache->plane.visible = plane_state->base.visible;
 
        if (!cache->plane.visible)
                return;
@@ -737,11 +761,11 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
        /* FIXME: We lack the proper locking here, so only run this on the
         * platforms that need. */
        if (IS_GEN(dev_priv, 5, 6))
-               cache->fb.ilk_ggtt_offset = i915_gem_obj_ggtt_offset(obj);
+               cache->fb.ilk_ggtt_offset = i915_gem_object_ggtt_offset(obj, NULL);
        cache->fb.pixel_format = fb->pixel_format;
        cache->fb.stride = fb->pitches[0];
-       cache->fb.fence_reg = obj->fence_reg;
-       cache->fb.tiling_mode = obj->tiling_mode;
+       cache->fb.fence_reg = get_fence_id(fb);
+       cache->fb.tiling_mode = i915_gem_object_get_tiling(obj);
 }
 
 static bool intel_fbc_can_activate(struct intel_crtc *crtc)
@@ -768,6 +792,10 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
 
        /* The use of a CPU fence is mandatory in order to detect writes
         * by the CPU to the scanout and trigger updates to the FBC.
+        *
+        * Note that is possible for a tiled surface to be unmappable (and
+        * so have no fence associated with it) due to aperture constaints
+        * at the time of pinning.
         */
        if (cache->fb.tiling_mode != I915_TILING_X ||
            cache->fb.fence_reg == I915_FENCE_REG_NONE) {
@@ -775,7 +803,7 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
                return false;
        }
        if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) &&
-           cache->plane.rotation != BIT(DRM_ROTATE_0)) {
+           cache->plane.rotation != DRM_ROTATE_0) {
                fbc->no_fbc_reason = "rotation unsupported";
                return false;
        }
@@ -1050,7 +1078,7 @@ void intel_fbc_choose_crtc(struct drm_i915_private *dev_priv,
                struct intel_plane_state *intel_plane_state =
                        to_intel_plane_state(plane_state);
 
-               if (!intel_plane_state->visible)
+               if (!intel_plane_state->base.visible)
                        continue;
 
                for_each_crtc_in_state(state, crtc, crtc_state, j) {
@@ -1075,6 +1103,8 @@ out:
 /**
  * intel_fbc_enable: tries to enable FBC on the CRTC
  * @crtc: the CRTC
+ * @crtc_state: corresponding &drm_crtc_state for @crtc
+ * @plane_state: corresponding &drm_plane_state for the primary plane of @crtc
  *
  * This function checks if the given CRTC was chosen for FBC, then enables it if
  * possible. Notice that it doesn't activate FBC. It is valid to call
@@ -1163,11 +1193,8 @@ void intel_fbc_disable(struct intel_crtc *crtc)
                return;
 
        mutex_lock(&fbc->lock);
-       if (fbc->crtc == crtc) {
-               WARN_ON(!fbc->enabled);
-               WARN_ON(fbc->active);
+       if (fbc->crtc == crtc)
                __intel_fbc_disable(dev_priv);
-       }
        mutex_unlock(&fbc->lock);
 
        cancel_work_sync(&fbc->work.work);
@@ -1212,7 +1239,7 @@ void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv)
 
        for_each_intel_crtc(&dev_priv->drm, crtc)
                if (intel_crtc_active(&crtc->base) &&
-                   to_intel_plane_state(crtc->base.primary->state)->visible)
+                   to_intel_plane_state(crtc->base.primary->state)->base.visible)
                        dev_priv->fbc.visible_pipes_mask |= (1 << crtc->pipe);
 }