diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-09-14 18:39:40 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-09-21 18:47:38 -0400 |
commit | 74dff282237ea8c0a5df1afd8526eac4b6cee063 (patch) | |
tree | fd6f5f1ffb281a96de3d9746e15233d538ea8555 /drivers/gpu/drm | |
parent | e70236a8d3d0a4c100a0b9f7d394d9bda9c56aca (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/drm')
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 51 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 79 |
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 | ||
1152 | static int i915_load_modeset_init(struct drm_device *dev, | 1165 | static 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; } | |||
827 | extern void intel_modeset_init(struct drm_device *dev); | 827 | extern void intel_modeset_init(struct drm_device *dev); |
828 | extern void intel_modeset_cleanup(struct drm_device *dev); | 828 | extern void intel_modeset_cleanup(struct drm_device *dev); |
829 | extern void i8xx_disable_fbc(struct drm_device *dev); | 829 | extern void i8xx_disable_fbc(struct drm_device *dev); |
830 | extern 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 | ||
1033 | static 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 | |||
1070 | void 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 | |||
1084 | static 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 */ |