]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
drm/i915: Add support for FBC on Ivybridge.
authorRodrigo Vivi <rodrigo.vivi@gmail.com>
Mon, 6 May 2013 22:37:33 +0000 (19:37 -0300)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 10 May 2013 19:56:47 +0000 (21:56 +0200)
This patch introduce Frame Buffer Compression (FBC) support for IVB,
without enabling it by default.
It adds a new function gen7_enable_fbc to avoid getting
ironlake_enable_fbc messed with many IS_IVYBRIDGE checks.

v2: Fixes from Ville.
      *  Fix Plane. FBC is tied to primary plane A in HSW
     *  Fix DPFC initial write to avoid let trash on the register.
v3: Checking for bad plane on intel_update_fbc() as Chris suggested.
v4: Ville pointed out that according to BSpec FBC_CTL bits 0:3 must be 0.
v5: Up to v4 this work was entirely focused on Haswell. However Ville
    noticed I could reuse the FBC work done for HSW and get FBC for free
    at Ivybridge. So it makes more sense enable FBC for IVB first.
    FBC for HSW comming on next patches. We are just not enabling it by
    default on IVB.
v6: Fix confused commit name (by Matt Turner).
v7: Remove gtt_offset shift since it is page aligned byte offset (by Ville).

Cc: Matt Turner <mattst88@gmail.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_pm.c

index 3cb27fa842ee854c558d9153b014a011c0ac3fd9..cd84f774aacef4a9a04649a574283ad981fd5162 100644 (file)
@@ -280,6 +280,7 @@ static const struct intel_device_info intel_ivybridge_m_info = {
        GEN7_FEATURES,
        .is_ivybridge = 1,
        .is_mobile = 1,
+       .has_fbc = 1,
 };
 
 static const struct intel_device_info intel_ivybridge_q_info = {
index a809a5633b28179781b6610e197f2d4f407cf7f8..a7fc13d28b5c3f7cec37e277bd3244d19b80906d 100644 (file)
 #define   DPFC_CTL_EN          (1<<31)
 #define   DPFC_CTL_PLANEA      (0<<30)
 #define   DPFC_CTL_PLANEB      (1<<30)
+#define   IVB_DPFC_CTL_PLANE_SHIFT     (29)
 #define   DPFC_CTL_FENCE_EN    (1<<29)
+#define   IVB_DPFC_CTL_FENCE_EN        (1<<28)
 #define   DPFC_CTL_PERSISTENT_MODE     (1<<25)
 #define   DPFC_SR_EN           (1<<10)
 #define   DPFC_CTL_LIMIT_1X    (0<<6)
 #define ILK_DPFC_CHICKEN       0x43224
 #define ILK_FBC_RT_BASE                0x2128
 #define   ILK_FBC_RT_VALID     (1<<0)
+#define   SNB_FBC_FRONT_BUFFER (1<<1)
 
 #define ILK_DISPLAY_CHICKEN1   0x42000
 #define   ILK_FBCQ_DIS         (1<<22)
 #define   SNB_CPU_FENCE_ENABLE (1<<29)
 #define DPFC_CPU_FENCE_OFFSET  0x100104
 
+/* Framebuffer compression for Ivybridge */
+#define IVB_FBC_RT_BASE                        0x7020
+
 
 /*
  * GPIO regs
index 5a22ce2b8244cd924ec128647456244f5193f2d6..e398963797a60b77fb65e636bceddd63648ef0a0 100644 (file)
@@ -253,6 +253,30 @@ static bool ironlake_fbc_enabled(struct drm_device *dev)
        return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
 }
 
+static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_framebuffer *fb = crtc->fb;
+       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+       struct drm_i915_gem_object *obj = intel_fb->obj;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+       I915_WRITE(IVB_FBC_RT_BASE, obj->gtt_offset | ILK_FBC_RT_VALID);
+
+       I915_WRITE(ILK_DPFC_CONTROL, DPFC_CTL_EN | DPFC_CTL_LIMIT_1X |
+                  IVB_DPFC_CTL_FENCE_EN |
+                  intel_crtc->plane << IVB_DPFC_CTL_PLANE_SHIFT);
+
+       I915_WRITE(SNB_DPFC_CTL_SA,
+                  SNB_CPU_FENCE_ENABLE | obj->fence_reg);
+       I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y);
+
+       sandybridge_blit_fbc_update(dev);
+
+       DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
+}
+
 bool intel_fbc_enabled(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -439,7 +463,7 @@ void intel_update_fbc(struct drm_device *dev)
        if (enable_fbc < 0) {
                DRM_DEBUG_KMS("fbc set to per-chip default\n");
                enable_fbc = 1;
-               if (INTEL_INFO(dev)->gen <= 6)
+               if (INTEL_INFO(dev)->gen <= 7)
                        enable_fbc = 0;
        }
        if (!enable_fbc) {
@@ -4507,7 +4531,12 @@ void intel_init_pm(struct drm_device *dev)
        if (I915_HAS_FBC(dev)) {
                if (HAS_PCH_SPLIT(dev)) {
                        dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
-                       dev_priv->display.enable_fbc = ironlake_enable_fbc;
+                       if (IS_IVYBRIDGE(dev))
+                               dev_priv->display.enable_fbc =
+                                       gen7_enable_fbc;
+                       else
+                               dev_priv->display.enable_fbc =
+                                       ironlake_enable_fbc;
                        dev_priv->display.disable_fbc = ironlake_disable_fbc;
                } else if (IS_GM45(dev)) {
                        dev_priv->display.fbc_enabled = g4x_fbc_enabled;