diff options
author | Zhao Yakui <yakui.zhao@intel.com> | 2010-06-12 02:32:27 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-08-01 22:03:44 -0400 |
commit | b52eb4dcab23fe0c52a437276258e0afcf913ef5 (patch) | |
tree | 72391fa2b4cf33155e078ab6467245403fbd3d18 /drivers/gpu/drm/i915/intel_display.c | |
parent | c936f44d1b2daea2fd1d52300cab792abe01e28c (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.c | 93 |
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 | ||
1126 | static 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 | |||
1166 | void 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 | |||
1180 | static 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 | |||
1126 | bool intel_fbc_enabled(struct drm_device *dev) | 1187 | bool 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; |