diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_suspend.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 93 |
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 | ||
135 | static const struct intel_device_info intel_ironlake_m_info = { | 135 | static 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); | |||
1042 | extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state); | 1042 | extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state); |
1043 | extern void i8xx_disable_fbc(struct drm_device *dev); | 1043 | extern void i8xx_disable_fbc(struct drm_device *dev); |
1044 | extern void g4x_disable_fbc(struct drm_device *dev); | 1044 | extern void g4x_disable_fbc(struct drm_device *dev); |
1045 | extern void ironlake_disable_fbc(struct drm_device *dev); | ||
1045 | extern void intel_disable_fbc(struct drm_device *dev); | 1046 | extern void intel_disable_fbc(struct drm_device *dev); |
1046 | extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval); | 1047 | extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval); |
1047 | extern bool intel_fbc_enabled(struct drm_device *dev); | 1048 | extern 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 | ||
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; |