aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2009-09-14 18:39:40 -0400
committerEric Anholt <eric@anholt.net>2009-09-21 18:47:38 -0400
commit74dff282237ea8c0a5df1afd8526eac4b6cee063 (patch)
treefd6f5f1ffb281a96de3d9746e15233d538ea8555 /drivers/gpu
parente70236a8d3d0a4c100a0b9f7d394d9bda9c56aca (diff)
drm/i915: framebuffer compression for GM45+
Add support for framebuffer compression on GM45 and above. Removes some unnecessary I915_HAS_FBC checks as well (this is now part of the FBC display function). Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c51
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h27
-rw-r--r--drivers/gpu/drm/i915/intel_display.c79
4 files changed, 132 insertions, 26 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 250999cdf814..59826c5b8760 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1119,34 +1119,47 @@ static void i915_setup_compression(struct drm_device *dev, int size)
1119 return; 1119 return;
1120 } 1120 }
1121 1121
1122 compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096, 4096, 0); 1122 cfb_base = i915_gtt_to_phys(dev, compressed_fb->start);
1123 if (!compressed_llb) { 1123 if (!cfb_base) {
1124 i915_warn_stolen(dev); 1124 DRM_ERROR("failed to get stolen phys addr, disabling FBC\n");
1125 return; 1125 drm_mm_put_block(compressed_fb);
1126 } 1126 }
1127 1127
1128 compressed_llb = drm_mm_get_block(compressed_llb, 4096, 4096); 1128 if (!IS_GM45(dev)) {
1129 if (!compressed_llb) { 1129 compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096,
1130 i915_warn_stolen(dev); 1130 4096, 0);
1131 return; 1131 if (!compressed_llb) {
1132 i915_warn_stolen(dev);
1133 return;
1134 }
1135
1136 compressed_llb = drm_mm_get_block(compressed_llb, 4096, 4096);
1137 if (!compressed_llb) {
1138 i915_warn_stolen(dev);
1139 return;
1140 }
1141
1142 ll_base = i915_gtt_to_phys(dev, compressed_llb->start);
1143 if (!ll_base) {
1144 DRM_ERROR("failed to get stolen phys addr, disabling FBC\n");
1145 drm_mm_put_block(compressed_fb);
1146 drm_mm_put_block(compressed_llb);
1147 }
1132 } 1148 }
1133 1149
1134 dev_priv->cfb_size = size; 1150 dev_priv->cfb_size = size;
1135 1151
1136 cfb_base = i915_gtt_to_phys(dev, compressed_fb->start); 1152 if (IS_GM45(dev)) {
1137 ll_base = i915_gtt_to_phys(dev, compressed_llb->start); 1153 g4x_disable_fbc(dev);
1138 if (!cfb_base || !ll_base) { 1154 I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
1139 DRM_ERROR("failed to get stolen phys addr, disabling FBC\n"); 1155 } else {
1140 drm_mm_put_block(compressed_fb); 1156 i8xx_disable_fbc(dev);
1141 drm_mm_put_block(compressed_llb); 1157 I915_WRITE(FBC_CFB_BASE, cfb_base);
1158 I915_WRITE(FBC_LL_BASE, ll_base);
1142 } 1159 }
1143 1160
1144 i8xx_disable_fbc(dev);
1145
1146 DRM_DEBUG("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base, 1161 DRM_DEBUG("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
1147 ll_base, size >> 20); 1162 ll_base, size >> 20);
1148 I915_WRITE(FBC_CFB_BASE, cfb_base);
1149 I915_WRITE(FBC_LL_BASE, ll_base);
1150} 1163}
1151 1164
1152static int i915_load_modeset_init(struct drm_device *dev, 1165static int i915_load_modeset_init(struct drm_device *dev,
@@ -1194,7 +1207,7 @@ static int i915_load_modeset_init(struct drm_device *dev,
1194 goto out; 1207 goto out;
1195 1208
1196 /* Try to set up FBC with a reasonable compressed buffer size */ 1209 /* Try to set up FBC with a reasonable compressed buffer size */
1197 if (IS_MOBILE(dev) && (IS_I9XX(dev) || IS_I965G(dev)) && 1210 if (IS_MOBILE(dev) && (IS_I9XX(dev) || IS_I965G(dev) || IS_GM45(dev)) &&
1198 i915_powersave) { 1211 i915_powersave) {
1199 int cfb_size; 1212 int cfb_size;
1200 1213
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ebdc639e9858..931087272854 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -827,6 +827,7 @@ static inline void opregion_enable_asle(struct drm_device *dev) { return; }
827extern void intel_modeset_init(struct drm_device *dev); 827extern void intel_modeset_init(struct drm_device *dev);
828extern void intel_modeset_cleanup(struct drm_device *dev); 828extern void intel_modeset_cleanup(struct drm_device *dev);
829extern void i8xx_disable_fbc(struct drm_device *dev); 829extern void i8xx_disable_fbc(struct drm_device *dev);
830extern void g4x_disable_fbc(struct drm_device *dev);
830 831
831/** 832/**
832 * Lock test for when it's just for synchronization of ring access. 833 * Lock test for when it's just for synchronization of ring access.
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f3d41397ce74..8122a72828e4 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -351,6 +351,33 @@
351 351
352#define FBC_LL_SIZE (1536) 352#define FBC_LL_SIZE (1536)
353 353
354/* Framebuffer compression for GM45+ */
355#define DPFC_CB_BASE 0x3200
356#define DPFC_CONTROL 0x3208
357#define DPFC_CTL_EN (1<<31)
358#define DPFC_CTL_PLANEA (0<<30)
359#define DPFC_CTL_PLANEB (1<<30)
360#define DPFC_CTL_FENCE_EN (1<<29)
361#define DPFC_SR_EN (1<<10)
362#define DPFC_CTL_LIMIT_1X (0<<6)
363#define DPFC_CTL_LIMIT_2X (1<<6)
364#define DPFC_CTL_LIMIT_4X (2<<6)
365#define DPFC_RECOMP_CTL 0x320c
366#define DPFC_RECOMP_STALL_EN (1<<27)
367#define DPFC_RECOMP_STALL_WM_SHIFT (16)
368#define DPFC_RECOMP_STALL_WM_MASK (0x07ff0000)
369#define DPFC_RECOMP_TIMER_COUNT_SHIFT (0)
370#define DPFC_RECOMP_TIMER_COUNT_MASK (0x0000003f)
371#define DPFC_STATUS 0x3210
372#define DPFC_INVAL_SEG_SHIFT (16)
373#define DPFC_INVAL_SEG_MASK (0x07ff0000)
374#define DPFC_COMP_SEG_SHIFT (0)
375#define DPFC_COMP_SEG_MASK (0x000003ff)
376#define DPFC_STATUS2 0x3214
377#define DPFC_FENCE_YOFF 0x3218
378#define DPFC_CHICKEN 0x3224
379#define DPFC_HT_MODIFY (1<<31)
380
354/* 381/*
355 * GPIO regs 382 * GPIO regs
356 */ 383 */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bac6c510fbaf..d995762ce4bc 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1030,6 +1030,65 @@ static bool i8xx_fbc_enabled(struct drm_crtc *crtc)
1030 return I915_READ(FBC_CONTROL) & FBC_CTL_EN; 1030 return I915_READ(FBC_CONTROL) & FBC_CTL_EN;
1031} 1031}
1032 1032
1033static void g4x_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
1034{
1035 struct drm_device *dev = crtc->dev;
1036 struct drm_i915_private *dev_priv = dev->dev_private;
1037 struct drm_framebuffer *fb = crtc->fb;
1038 struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
1039 struct drm_i915_gem_object *obj_priv = intel_fb->obj->driver_private;
1040 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
1041 int plane = (intel_crtc->plane == 0 ? DPFC_CTL_PLANEA :
1042 DPFC_CTL_PLANEB);
1043 unsigned long stall_watermark = 200;
1044 u32 dpfc_ctl;
1045
1046 dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1;
1047 dev_priv->cfb_fence = obj_priv->fence_reg;
1048 dev_priv->cfb_plane = intel_crtc->plane;
1049
1050 dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X;
1051 if (obj_priv->tiling_mode != I915_TILING_NONE) {
1052 dpfc_ctl |= DPFC_CTL_FENCE_EN | dev_priv->cfb_fence;
1053 I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY);
1054 } else {
1055 I915_WRITE(DPFC_CHICKEN, ~DPFC_HT_MODIFY);
1056 }
1057
1058 I915_WRITE(DPFC_CONTROL, dpfc_ctl);
1059 I915_WRITE(DPFC_RECOMP_CTL, DPFC_RECOMP_STALL_EN |
1060 (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) |
1061 (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT));
1062 I915_WRITE(DPFC_FENCE_YOFF, crtc->y);
1063
1064 /* enable it... */
1065 I915_WRITE(DPFC_CONTROL, I915_READ(DPFC_CONTROL) | DPFC_CTL_EN);
1066
1067 DRM_DEBUG("enabled fbc on plane %d\n", intel_crtc->plane);
1068}
1069
1070void g4x_disable_fbc(struct drm_device *dev)
1071{
1072 struct drm_i915_private *dev_priv = dev->dev_private;
1073 u32 dpfc_ctl;
1074
1075 /* Disable compression */
1076 dpfc_ctl = I915_READ(DPFC_CONTROL);
1077 dpfc_ctl &= ~DPFC_CTL_EN;
1078 I915_WRITE(DPFC_CONTROL, dpfc_ctl);
1079 intel_wait_for_vblank(dev);
1080
1081 DRM_DEBUG("disabled FBC\n");
1082}
1083
1084static bool g4x_fbc_enabled(struct drm_crtc *crtc)
1085{
1086 struct drm_device *dev = crtc->dev;
1087 struct drm_i915_private *dev_priv = dev->dev_private;
1088
1089 return I915_READ(DPFC_CONTROL) & DPFC_CTL_EN;
1090}
1091
1033/** 1092/**
1034 * intel_update_fbc - enable/disable FBC as needed 1093 * intel_update_fbc - enable/disable FBC as needed
1035 * @crtc: CRTC to point the compressor at 1094 * @crtc: CRTC to point the compressor at
@@ -1097,7 +1156,7 @@ static void intel_update_fbc(struct drm_crtc *crtc,
1097 DRM_DEBUG("mode too large for compression, disabling\n"); 1156 DRM_DEBUG("mode too large for compression, disabling\n");
1098 goto out_disable; 1157 goto out_disable;
1099 } 1158 }
1100 if (IS_I9XX(dev) && plane != 0) { 1159 if ((IS_I915GM(dev) || IS_I945GM(dev)) && plane != 0) {
1101 DRM_DEBUG("plane not 0, disabling compression\n"); 1160 DRM_DEBUG("plane not 0, disabling compression\n");
1102 goto out_disable; 1161 goto out_disable;
1103 } 1162 }
@@ -1265,7 +1324,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
1265 I915_READ(dspbase); 1324 I915_READ(dspbase);
1266 } 1325 }
1267 1326
1268 if (I915_HAS_FBC(dev) && (IS_I965G(dev) || plane == 0)) 1327 if ((IS_I965G(dev) || plane == 0))
1269 intel_update_fbc(crtc, &crtc->mode); 1328 intel_update_fbc(crtc, &crtc->mode);
1270 1329
1271 intel_wait_for_vblank(dev); 1330 intel_wait_for_vblank(dev);
@@ -1774,7 +1833,8 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
1774 1833
1775 intel_crtc_load_lut(crtc); 1834 intel_crtc_load_lut(crtc);
1776 1835
1777 intel_update_fbc(crtc, &crtc->mode); 1836 if ((IS_I965G(dev) || plane == 0))
1837 intel_update_fbc(crtc, &crtc->mode);
1778 1838
1779 /* Give the overlay scaler a chance to enable if it's on this pipe */ 1839 /* Give the overlay scaler a chance to enable if it's on this pipe */
1780 //intel_crtc_dpms_video(crtc, true); TODO 1840 //intel_crtc_dpms_video(crtc, true); TODO
@@ -2988,7 +3048,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
2988 /* Flush the plane changes */ 3048 /* Flush the plane changes */
2989 ret = intel_pipe_set_base(crtc, x, y, old_fb); 3049 ret = intel_pipe_set_base(crtc, x, y, old_fb);
2990 3050
2991 intel_update_fbc(crtc, &crtc->mode); 3051 if ((IS_I965G(dev) || plane == 0))
3052 intel_update_fbc(crtc, &crtc->mode);
2992 3053
2993 intel_update_watermarks(dev); 3054 intel_update_watermarks(dev);
2994 3055
@@ -3121,7 +3182,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
3121 drm_gem_object_unreference(intel_crtc->cursor_bo); 3182 drm_gem_object_unreference(intel_crtc->cursor_bo);
3122 } 3183 }
3123 3184
3124 if (I915_HAS_FBC(dev) && (IS_I965G(dev) || plane == 0)) 3185 if ((IS_I965G(dev) || plane == 0))
3125 intel_update_fbc(crtc, &crtc->mode); 3186 intel_update_fbc(crtc, &crtc->mode);
3126 3187
3127 mutex_unlock(&dev->struct_mutex); 3188 mutex_unlock(&dev->struct_mutex);
@@ -4108,12 +4169,16 @@ static void intel_init_display(struct drm_device *dev)
4108 4169
4109 /* Only mobile has FBC, leave pointers NULL for other chips */ 4170 /* Only mobile has FBC, leave pointers NULL for other chips */
4110 if (IS_MOBILE(dev)) { 4171 if (IS_MOBILE(dev)) {
4111 /* 855GM needs testing */ 4172 if (IS_GM45(dev)) {
4112 if (IS_I965GM(dev) || IS_I945GM(dev) || IS_I915GM(dev)) { 4173 dev_priv->display.fbc_enabled = g4x_fbc_enabled;
4174 dev_priv->display.enable_fbc = g4x_enable_fbc;
4175 dev_priv->display.disable_fbc = g4x_disable_fbc;
4176 } else if (IS_I965GM(dev) || IS_I945GM(dev) || IS_I915GM(dev)) {
4113 dev_priv->display.fbc_enabled = i8xx_fbc_enabled; 4177 dev_priv->display.fbc_enabled = i8xx_fbc_enabled;
4114 dev_priv->display.enable_fbc = i8xx_enable_fbc; 4178 dev_priv->display.enable_fbc = i8xx_enable_fbc;
4115 dev_priv->display.disable_fbc = i8xx_disable_fbc; 4179 dev_priv->display.disable_fbc = i8xx_disable_fbc;
4116 } 4180 }
4181 /* 855GM needs testing */
4117 } 4182 }
4118 4183
4119 /* Returns the core display clock speed */ 4184 /* Returns the core display clock speed */