aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c9
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h19
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c9
-rw-r--r--drivers/gpu/drm/i915/intel_display.c93
6 files changed, 125 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 92898035845d..9ddb7b5ac057 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1257,7 +1257,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
1257 drm_mm_put_block(compressed_fb); 1257 drm_mm_put_block(compressed_fb);
1258 } 1258 }
1259 1259
1260 if (!IS_GM45(dev)) { 1260 if (!(IS_GM45(dev) || IS_IRONLAKE_M(dev))) {
1261 compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096, 1261 compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096,
1262 4096, 0); 1262 4096, 0);
1263 if (!compressed_llb) { 1263 if (!compressed_llb) {
@@ -1283,8 +1283,9 @@ static void i915_setup_compression(struct drm_device *dev, int size)
1283 1283
1284 intel_disable_fbc(dev); 1284 intel_disable_fbc(dev);
1285 dev_priv->compressed_fb = compressed_fb; 1285 dev_priv->compressed_fb = compressed_fb;
1286 1286 if (IS_IRONLAKE_M(dev))
1287 if (IS_GM45(dev)) { 1287 I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
1288 else if (IS_GM45(dev)) {
1288 I915_WRITE(DPFC_CB_BASE, compressed_fb->start); 1289 I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
1289 } else { 1290 } else {
1290 I915_WRITE(FBC_CFB_BASE, cfb_base); 1291 I915_WRITE(FBC_CFB_BASE, cfb_base);
@@ -1292,7 +1293,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
1292 dev_priv->compressed_llb = compressed_llb; 1293 dev_priv->compressed_llb = compressed_llb;
1293 } 1294 }
1294 1295
1295 DRM_DEBUG("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base, 1296 DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
1296 ll_base, size >> 20); 1297 ll_base, size >> 20);
1297} 1298}
1298 1299
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 65d3f3e8475b..b5694d24b541 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -134,7 +134,7 @@ static const struct intel_device_info intel_ironlake_d_info = {
134 134
135static const struct intel_device_info intel_ironlake_m_info = { 135static const struct intel_device_info intel_ironlake_m_info = {
136 .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1, 136 .is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
137 .need_gfx_hws = 1, .has_rc6 = 1, 137 .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
138 .has_hotplug = 1, 138 .has_hotplug = 1,
139}; 139};
140 140
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7fba852455f4..f5636d8da96d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1042,6 +1042,7 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
1042extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state); 1042extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
1043extern void i8xx_disable_fbc(struct drm_device *dev); 1043extern void i8xx_disable_fbc(struct drm_device *dev);
1044extern void g4x_disable_fbc(struct drm_device *dev); 1044extern void g4x_disable_fbc(struct drm_device *dev);
1045extern void ironlake_disable_fbc(struct drm_device *dev);
1045extern void intel_disable_fbc(struct drm_device *dev); 1046extern void intel_disable_fbc(struct drm_device *dev);
1046extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval); 1047extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
1047extern bool intel_fbc_enabled(struct drm_device *dev); 1048extern bool intel_fbc_enabled(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index d0ccfa0c72de..e2a6f687d8b0 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -530,6 +530,21 @@
530#define DPFC_CHICKEN 0x3224 530#define DPFC_CHICKEN 0x3224
531#define DPFC_HT_MODIFY (1<<31) 531#define DPFC_HT_MODIFY (1<<31)
532 532
533/* Framebuffer compression for Ironlake */
534#define ILK_DPFC_CB_BASE 0x43200
535#define ILK_DPFC_CONTROL 0x43208
536/* The bit 28-8 is reserved */
537#define DPFC_RESERVED (0x1FFFFF00)
538#define ILK_DPFC_RECOMP_CTL 0x4320c
539#define ILK_DPFC_STATUS 0x43210
540#define ILK_DPFC_FENCE_YOFF 0x43218
541#define ILK_DPFC_CHICKEN 0x43224
542#define ILK_FBC_RT_BASE 0x2128
543#define ILK_FBC_RT_VALID (1<<0)
544
545#define ILK_DISPLAY_CHICKEN1 0x42000
546#define ILK_FBCQ_DIS (1<<22)
547
533/* 548/*
534 * GPIO regs 549 * GPIO regs
535 */ 550 */
@@ -2491,6 +2506,10 @@
2491#define ILK_VSDPFD_FULL (1<<21) 2506#define ILK_VSDPFD_FULL (1<<21)
2492#define ILK_DSPCLK_GATE 0x42020 2507#define ILK_DSPCLK_GATE 0x42020
2493#define ILK_DPARB_CLK_GATE (1<<5) 2508#define ILK_DPARB_CLK_GATE (1<<5)
2509/* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */
2510#define ILK_CLK_FBC (1<<7)
2511#define ILK_DPFC_DIS1 (1<<8)
2512#define ILK_DPFC_DIS2 (1<<9)
2494 2513
2495#define DISP_ARB_CTL 0x45000 2514#define DISP_ARB_CTL 0x45000
2496#define DISP_TILE_SURFACE_SWIZZLING (1<<13) 2515#define DISP_TILE_SURFACE_SWIZZLING (1<<13)
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 60a5800fba6e..6e2025274db5 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -602,7 +602,9 @@ void i915_save_display(struct drm_device *dev)
602 602
603 /* Only save FBC state on the platform that supports FBC */ 603 /* Only save FBC state on the platform that supports FBC */
604 if (I915_HAS_FBC(dev)) { 604 if (I915_HAS_FBC(dev)) {
605 if (IS_GM45(dev)) { 605 if (IS_IRONLAKE_M(dev)) {
606 dev_priv->saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
607 } else if (IS_GM45(dev)) {
606 dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE); 608 dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
607 } else { 609 } else {
608 dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE); 610 dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
@@ -706,7 +708,10 @@ void i915_restore_display(struct drm_device *dev)
706 708
707 /* only restore FBC info on the platform that supports FBC*/ 709 /* only restore FBC info on the platform that supports FBC*/
708 if (I915_HAS_FBC(dev)) { 710 if (I915_HAS_FBC(dev)) {
709 if (IS_GM45(dev)) { 711 if (IS_IRONLAKE_M(dev)) {
712 ironlake_disable_fbc(dev);
713 I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
714 } else if (IS_GM45(dev)) {
710 g4x_disable_fbc(dev); 715 g4x_disable_fbc(dev);
711 I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE); 716 I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
712 } else { 717 } else {
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;