OSDN Git Service

drm/i915/fbc: Require linear fb stride to be multiple of 512 bytes on gen9/glk
[tomoyo/tomoyo-test1.git] / drivers / gpu / drm / i915 / display / intel_fbc.c
index 2e5d835..7194f9b 100644 (file)
@@ -104,7 +104,7 @@ static void i8xx_fbc_deactivate(struct drm_i915_private *dev_priv)
        /* Wait for compressing bit to clear */
        if (intel_de_wait_for_clear(dev_priv, FBC_STATUS,
                                    FBC_STAT_COMPRESSING, 10)) {
-               DRM_DEBUG_KMS("FBC idle timed out\n");
+               drm_dbg_kms(&dev_priv->drm, "FBC idle timed out\n");
                return;
        }
 }
@@ -485,8 +485,8 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv,
        if (!ret)
                goto err_llb;
        else if (ret > 1) {
-               DRM_INFO("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
-
+               drm_info_once(&dev_priv->drm,
+                             "Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
        }
 
        fbc->threshold = ret;
@@ -521,8 +521,9 @@ static int intel_fbc_alloc_cfb(struct drm_i915_private *dev_priv,
                               dev_priv->dsm.start + compressed_llb->start);
        }
 
-       DRM_DEBUG_KMS("reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n",
-                     fbc->compressed_fb.size, fbc->threshold);
+       drm_dbg_kms(&dev_priv->drm,
+                   "reserved %llu bytes of contiguous stolen space for FBC, threshold: %d\n",
+                   fbc->compressed_fb.size, fbc->threshold);
 
        return 0;
 
@@ -531,7 +532,7 @@ err_fb:
        i915_gem_stolen_remove_node(dev_priv, &fbc->compressed_fb);
 err_llb:
        if (drm_mm_initialized(&dev_priv->mm.stolen))
-               pr_info_once("drm: not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
+               drm_info_once(&dev_priv->drm, "not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
        return -ENOSPC;
 }
 
@@ -563,7 +564,7 @@ void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv)
 }
 
 static bool stride_is_valid(struct drm_i915_private *dev_priv,
-                           unsigned int stride)
+                           u64 modifier, unsigned int stride)
 {
        /* This should have been caught earlier. */
        if (drm_WARN_ON_ONCE(&dev_priv->drm, (stride & (64 - 1)) != 0))
@@ -579,6 +580,11 @@ static bool stride_is_valid(struct drm_i915_private *dev_priv,
        if (IS_GEN(dev_priv, 4) && !IS_G4X(dev_priv) && stride < 2048)
                return false;
 
+       /* Display WA #1105: skl,bxt,kbl,cfl,glk */
+       if (IS_GEN(dev_priv, 9) &&
+           modifier == DRM_FORMAT_MOD_LINEAR && stride & 511)
+               return false;
+
        if (stride > 16384)
                return false;
 
@@ -606,6 +612,19 @@ static bool pixel_format_is_valid(struct drm_i915_private *dev_priv,
        }
 }
 
+static bool rotation_is_valid(struct drm_i915_private *dev_priv,
+                             u32 pixel_format, unsigned int rotation)
+{
+       if (INTEL_GEN(dev_priv) >= 9 && pixel_format == DRM_FORMAT_RGB565 &&
+           drm_rotation_90_or_270(rotation))
+               return false;
+       else if (INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv) &&
+                rotation != DRM_MODE_ROTATE_0)
+               return false;
+
+       return true;
+}
+
 /*
  * For some reason, the hardware tracking starts looking at whatever we
  * programmed as the display plane base address register. It does not look at
@@ -640,6 +659,22 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc)
        return effective_w <= max_w && effective_h <= max_h;
 }
 
+static bool tiling_is_valid(struct drm_i915_private *dev_priv,
+                           uint64_t modifier)
+{
+       switch (modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+               if (INTEL_GEN(dev_priv) >= 9)
+                       return true;
+               return false;
+       case I915_FORMAT_MOD_X_TILED:
+       case I915_FORMAT_MOD_Y_TILED:
+               return true;
+       default:
+               return false;
+       }
+}
+
 static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
                                         const struct intel_crtc_state *crtc_state,
                                         const struct intel_plane_state *plane_state)
@@ -673,6 +708,7 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
 
        cache->fb.format = fb->format;
        cache->fb.stride = fb->pitches[0];
+       cache->fb.modifier = fb->modifier;
 
        drm_WARN_ON(&dev_priv->drm, plane_state->flags & PLANE_HAS_FENCE &&
                    !plane_state->vma->fence);
@@ -746,30 +782,40 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc)
                return false;
        }
 
-       /* 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.
+       /* The use of a CPU fence is one of two ways to detect writes by the
+        * CPU to the scanout and trigger updates to the FBC.
+        *
+        * The other method is by software tracking (see
+        * intel_fbc_invalidate/flush()), it will manually notify FBC and nuke
+        * the current compressed buffer and recompress it.
         *
         * Note that is possible for a tiled surface to be unmappable (and
-        * so have no fence associated with it) due to aperture constaints
+        * so have no fence associated with it) due to aperture constraints
         * at the time of pinning.
         *
         * FIXME with 90/270 degree rotation we should use the fence on
         * the normal GTT view (the rotated view doesn't even have a
         * fence). Would need changes to the FBC fence Y offset as well.
-        * For now this will effecively disable FBC with 90/270 degree
+        * For now this will effectively disable FBC with 90/270 degree
         * rotation.
         */
-       if (cache->fence_id < 0) {
+       if (INTEL_GEN(dev_priv) < 9 && cache->fence_id < 0) {
                fbc->no_fbc_reason = "framebuffer not tiled or fenced";
                return false;
        }
-       if (INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv) &&
-           cache->plane.rotation != DRM_MODE_ROTATE_0) {
+
+       if (!rotation_is_valid(dev_priv, cache->fb.format->format,
+                              cache->plane.rotation)) {
                fbc->no_fbc_reason = "rotation unsupported";
                return false;
        }
 
-       if (!stride_is_valid(dev_priv, cache->fb.stride)) {
+       if (!tiling_is_valid(dev_priv, cache->fb.modifier)) {
+               fbc->no_fbc_reason = "tiling unsupported";
+               return false;
+       }
+
+       if (!stride_is_valid(dev_priv, cache->fb.modifier, cache->fb.stride)) {
                fbc->no_fbc_reason = "framebuffer stride not supported";
                return false;
        }
@@ -948,7 +994,8 @@ static void __intel_fbc_disable(struct drm_i915_private *dev_priv)
        drm_WARN_ON(&dev_priv->drm, !fbc->crtc);
        drm_WARN_ON(&dev_priv->drm, fbc->active);
 
-       DRM_DEBUG_KMS("Disabling FBC on pipe %c\n", pipe_name(crtc->pipe));
+       drm_dbg_kms(&dev_priv->drm, "Disabling FBC on pipe %c\n",
+                   pipe_name(crtc->pipe));
 
        __intel_fbc_cleanup_cfb(dev_priv);
 
@@ -1176,7 +1223,8 @@ void intel_fbc_enable(struct intel_atomic_state *state,
        else
                cache->gen9_wa_cfb_stride = 0;
 
-       DRM_DEBUG_KMS("Enabling FBC on pipe %c\n", pipe_name(crtc->pipe));
+       drm_dbg_kms(&dev_priv->drm, "Enabling FBC on pipe %c\n",
+                   pipe_name(crtc->pipe));
        fbc->no_fbc_reason = "FBC enabled but not active yet\n";
 
        fbc->crtc = crtc;
@@ -1238,7 +1286,7 @@ static void intel_fbc_underrun_work_fn(struct work_struct *work)
        if (fbc->underrun_detected || !fbc->crtc)
                goto out;
 
-       DRM_DEBUG_KMS("Disabling FBC due to FIFO underrun.\n");
+       drm_dbg_kms(&dev_priv->drm, "Disabling FBC due to FIFO underrun.\n");
        fbc->underrun_detected = true;
 
        intel_fbc_deactivate(dev_priv, "FIFO underrun");
@@ -1264,7 +1312,8 @@ int intel_fbc_reset_underrun(struct drm_i915_private *dev_priv)
                return ret;
 
        if (dev_priv->fbc.underrun_detected) {
-               DRM_DEBUG_KMS("Re-allowing FBC after fifo underrun\n");
+               drm_dbg_kms(&dev_priv->drm,
+                           "Re-allowing FBC after fifo underrun\n");
                dev_priv->fbc.no_fbc_reason = "FIFO underrun cleared";
        }
 
@@ -1335,7 +1384,8 @@ static bool need_fbc_vtd_wa(struct drm_i915_private *dev_priv)
        /* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */
        if (intel_vtd_active() &&
            (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))) {
-               DRM_INFO("Disabling framebuffer compression (FBC) to prevent screen flicker with VT-d enabled\n");
+               drm_info(&dev_priv->drm,
+                        "Disabling framebuffer compression (FBC) to prevent screen flicker with VT-d enabled\n");
                return true;
        }
 
@@ -1363,8 +1413,8 @@ void intel_fbc_init(struct drm_i915_private *dev_priv)
                mkwrite_device_info(dev_priv)->display.has_fbc = false;
 
        i915_modparams.enable_fbc = intel_sanitize_fbc_option(dev_priv);
-       DRM_DEBUG_KMS("Sanitized enable_fbc value: %d\n",
-                     i915_modparams.enable_fbc);
+       drm_dbg_kms(&dev_priv->drm, "Sanitized enable_fbc value: %d\n",
+                   i915_modparams.enable_fbc);
 
        if (!HAS_FBC(dev_priv)) {
                fbc->no_fbc_reason = "unsupported by this chipset";