aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2010-06-12 02:32:27 -0400
committerEric Anholt <eric@anholt.net>2010-08-01 22:03:44 -0400
commitb52eb4dcab23fe0c52a437276258e0afcf913ef5 (patch)
tree72391fa2b4cf33155e078ab6467245403fbd3d18 /drivers/gpu/drm/i915/intel_display.c
parentc936f44d1b2daea2fd1d52300cab792abe01e28c (diff)
drm/i915: Add frame buffer compression support on Ironlake mobile
About 0.2W power can be saved on one HP laptop. Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c93
1 files changed, 92 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index cca6ce80d464..f2f812e15e61 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1123,6 +1123,67 @@ static bool g4x_fbc_enabled(struct drm_device *dev)
1123 return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN; 1123 return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
1124} 1124}
1125 1125
1126static void ironlake_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
1127{
1128 struct drm_device *dev = crtc->dev;
1129 struct drm_i915_private *dev_priv = dev->dev_private;
1130 struct drm_framebuffer *fb = crtc->fb;
1131 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
1132 struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj);
1133 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1134 int plane = (intel_crtc->plane == 0) ? DPFC_CTL_PLANEA :
1135 DPFC_CTL_PLANEB;
1136 unsigned long stall_watermark = 200;
1137 u32 dpfc_ctl;
1138
1139 dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
1140 dev_priv->cfb_fence = obj_priv->fence_reg;
1141 dev_priv->cfb_plane = intel_crtc->plane;
1142
1143 dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
1144 dpfc_ctl &= DPFC_RESERVED;
1145 dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X);
1146 if (obj_priv->tiling_mode != I915_TILING_NONE) {
1147 dpfc_ctl |= (DPFC_CTL_FENCE_EN | dev_priv->cfb_fence);
1148 I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY);
1149 } else {
1150 I915_WRITE(ILK_DPFC_CHICKEN, ~DPFC_HT_MODIFY);
1151 }
1152
1153 I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
1154 I915_WRITE(ILK_DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
1155 (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
1156 (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
1157 I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y);
1158 I915_WRITE(ILK_FBC_RT_BASE, obj_priv->gtt_offset | ILK_FBC_RT_VALID);
1159 /* enable it... */
1160 I915_WRITE(ILK_DPFC_CONTROL, I915_READ(ILK_DPFC_CONTROL) |
1161 DPFC_CTL_EN);
1162
1163 DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane);
1164}
1165
1166void ironlake_disable_fbc(struct drm_device *dev)
1167{
1168 struct drm_i915_private *dev_priv = dev->dev_private;
1169 u32 dpfc_ctl;
1170
1171 /* Disable compression */
1172 dpfc_ctl = I915_READ(ILK_DPFC_CONTROL);
1173 dpfc_ctl &= ~DPFC_CTL_EN;
1174 I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl);
1175 intel_wait_for_vblank(dev);
1176
1177 DRM_DEBUG_KMS("disabled FBC\n");
1178}
1179
1180static bool ironlake_fbc_enabled(struct drm_device *dev)
1181{
1182 struct drm_i915_private *dev_priv = dev->dev_private;
1183
1184 return I915_READ(ILK_DPFC_CONTROL) & DPFC_CTL_EN;
1185}
1186
1126bool intel_fbc_enabled(struct drm_device *dev) 1187bool intel_fbc_enabled(struct drm_device *dev)
1127{ 1188{
1128 struct drm_i915_private *dev_priv = dev->dev_private; 1189 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1966,6 +2027,8 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
1966 2027
1967 intel_crtc_load_lut(crtc); 2028 intel_crtc_load_lut(crtc);
1968 2029
2030 intel_update_fbc(crtc, &crtc->mode);
2031
1969 break; 2032 break;
1970 case DRM_MODE_DPMS_OFF: 2033 case DRM_MODE_DPMS_OFF:
1971 DRM_DEBUG_KMS("crtc %d dpms off\n", pipe); 2034 DRM_DEBUG_KMS("crtc %d dpms off\n", pipe);
@@ -1980,6 +2043,10 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
1980 I915_READ(dspbase_reg); 2043 I915_READ(dspbase_reg);
1981 } 2044 }
1982 2045
2046 if (dev_priv->cfb_plane == plane &&
2047 dev_priv->display.disable_fbc)
2048 dev_priv->display.disable_fbc(dev);
2049
1983 i915_disable_vga(dev); 2050 i915_disable_vga(dev);
1984 2051
1985 /* disable cpu pipe, disable after all planes disabled */ 2052 /* disable cpu pipe, disable after all planes disabled */
@@ -5452,6 +5519,26 @@ void intel_init_clock_gating(struct drm_device *dev)
5452 (I915_READ(DISP_ARB_CTL) | 5519 (I915_READ(DISP_ARB_CTL) |
5453 DISP_FBC_WM_DIS)); 5520 DISP_FBC_WM_DIS));
5454 } 5521 }
5522 /*
5523 * Based on the document from hardware guys the following bits
5524 * should be set unconditionally in order to enable FBC.
5525 * The bit 22 of 0x42000
5526 * The bit 22 of 0x42004
5527 * The bit 7,8,9 of 0x42020.
5528 */
5529 if (IS_IRONLAKE_M(dev)) {
5530 I915_WRITE(ILK_DISPLAY_CHICKEN1,
5531 I915_READ(ILK_DISPLAY_CHICKEN1) |
5532 ILK_FBCQ_DIS);
5533 I915_WRITE(ILK_DISPLAY_CHICKEN2,
5534 I915_READ(ILK_DISPLAY_CHICKEN2) |
5535 ILK_DPARB_GATE);
5536 I915_WRITE(ILK_DSPCLK_GATE,
5537 I915_READ(ILK_DSPCLK_GATE) |
5538 ILK_DPFC_DIS1 |
5539 ILK_DPFC_DIS2 |
5540 ILK_CLK_FBC);
5541 }
5455 return; 5542 return;
5456 } else if (IS_G4X(dev)) { 5543 } else if (IS_G4X(dev)) {
5457 uint32_t dspclk_gate; 5544 uint32_t dspclk_gate;
@@ -5530,7 +5617,11 @@ static void intel_init_display(struct drm_device *dev)
5530 dev_priv->display.dpms = i9xx_crtc_dpms; 5617 dev_priv->display.dpms = i9xx_crtc_dpms;
5531 5618
5532 if (I915_HAS_FBC(dev)) { 5619 if (I915_HAS_FBC(dev)) {
5533 if (IS_GM45(dev)) { 5620 if (IS_IRONLAKE_M(dev)) {
5621 dev_priv->display.fbc_enabled = ironlake_fbc_enabled;
5622 dev_priv->display.enable_fbc = ironlake_enable_fbc;
5623 dev_priv->display.disable_fbc = ironlake_disable_fbc;
5624 } else if (IS_GM45(dev)) {
5534 dev_priv->display.fbc_enabled = g4x_fbc_enabled; 5625 dev_priv->display.fbc_enabled = g4x_fbc_enabled;
5535 dev_priv->display.enable_fbc = g4x_enable_fbc; 5626 dev_priv->display.enable_fbc = g4x_enable_fbc;
5536 dev_priv->display.disable_fbc = g4x_disable_fbc; 5627 dev_priv->display.disable_fbc = g4x_disable_fbc;