diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 3cb27fa842ee854c558d9153b014a011c0ac3fd9..cd84f774aacef4a9a04649a574283ad981fd5162 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -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 = { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a809a5633b28179781b6610e197f2d4f407cf7f8..a7fc13d28b5c3f7cec37e277bd3244d19b80906d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -925,7 +925,9 @@ #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) @@ -958,6 +960,7 @@ #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) @@ -973,6 +976,9 @@ #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 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5a22ce2b8244cd924ec128647456244f5193f2d6..e398963797a60b77fb65e636bceddd63648ef0a0 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -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;