aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPaulo Zanoni <paulo.r.zanoni@intel.com>2013-05-31 15:33:22 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-05-31 15:39:55 -0400
commit42db64efcd95014570835c7b0a08277c60486f07 (patch)
treefecea5bb8b671eeaeadbf5df38559e89dc451cbe /drivers
parente7a639c445e1f7c44adc1665539fa8e3af0b8e30 (diff)
drm/i915: implement IPS feature
Intermediate Pixel Storage is a feature that should reduce the number of times the display engine wakes up memory to read pixels, so it should allow deeper PC states. IPS can only be enabled on ULT pipe A with 8:8:8 pipe pixel formats. With eDP 1920x1080 and correct watermarks but without FBC this moves my PC7 residency from 2.5% to around 38%. v2: - It's tied to pipe A, not port A - Add pipe_config support (Chris) - Add some assertions (Chris) - Rebase against latest dinq v3: - Don't ever set ips_enabled to false (Daniel) - Only check for ips_enabled at hsw_disable_ips (Daniel) v4: - Add hsw_compute_ips_config (Daniel) - Use the new dump_pipe_config (Daniel) Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h11
-rw-r--r--drivers/gpu/drm/i915/intel_display.c78
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
3 files changed, 88 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 89fac19d3249..5a593d20036c 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1023,6 +1023,8 @@
1023/* Framebuffer compression for Ivybridge */ 1023/* Framebuffer compression for Ivybridge */
1024#define IVB_FBC_RT_BASE 0x7020 1024#define IVB_FBC_RT_BASE 0x7020
1025 1025
1026#define IPS_CTL 0x43408
1027#define IPS_ENABLE (1 << 31)
1026 1028
1027#define _HSW_PIPE_SLICE_CHICKEN_1_A 0x420B0 1029#define _HSW_PIPE_SLICE_CHICKEN_1_A 0x420B0
1028#define _HSW_PIPE_SLICE_CHICKEN_1_B 0x420B4 1030#define _HSW_PIPE_SLICE_CHICKEN_1_B 0x420B4
@@ -3666,6 +3668,15 @@
3666#define _LGC_PALETTE_B 0x4a800 3668#define _LGC_PALETTE_B 0x4a800
3667#define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B) 3669#define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B)
3668 3670
3671#define _GAMMA_MODE_A 0x4a480
3672#define _GAMMA_MODE_B 0x4ac80
3673#define GAMMA_MODE(pipe) _PIPE(pipe, _GAMMA_MODE_A, _GAMMA_MODE_B)
3674#define GAMMA_MODE_MODE_MASK (3 << 0)
3675#define GAMMA_MODE_MODE_8bit (0 << 0)
3676#define GAMMA_MODE_MODE_10bit (1 << 0)
3677#define GAMMA_MODE_MODE_12bit (2 << 0)
3678#define GAMMA_MODE_MODE_SPLIT (3 << 0)
3679
3669/* interrupts */ 3680/* interrupts */
3670#define DE_MASTER_IRQ_CONTROL (1 << 31) 3681#define DE_MASTER_IRQ_CONTROL (1 << 31)
3671#define DE_SPRITEB_FLIP_DONE (1 << 29) 3682#define DE_SPRITEB_FLIP_DONE (1 << 29)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2e2c6a370f52..acfc6a164a59 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3242,6 +3242,42 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
3242 intel_wait_for_vblank(dev, intel_crtc->pipe); 3242 intel_wait_for_vblank(dev, intel_crtc->pipe);
3243} 3243}
3244 3244
3245/* IPS only exists on ULT machines and is tied to pipe A. */
3246static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
3247{
3248 return IS_ULT(crtc->base.dev) && crtc->pipe == PIPE_A;
3249}
3250
3251static void hsw_enable_ips(struct intel_crtc *crtc)
3252{
3253 struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
3254
3255 if (!crtc->config.ips_enabled)
3256 return;
3257
3258 /* We can only enable IPS after we enable a plane and wait for a vblank.
3259 * We guarantee that the plane is enabled by calling intel_enable_ips
3260 * only after intel_enable_plane. And intel_enable_plane already waits
3261 * for a vblank, so all we need to do here is to enable the IPS bit. */
3262 assert_plane_enabled(dev_priv, crtc->plane);
3263 I915_WRITE(IPS_CTL, IPS_ENABLE);
3264}
3265
3266static void hsw_disable_ips(struct intel_crtc *crtc)
3267{
3268 struct drm_device *dev = crtc->base.dev;
3269 struct drm_i915_private *dev_priv = dev->dev_private;
3270
3271 if (!crtc->config.ips_enabled)
3272 return;
3273
3274 assert_plane_enabled(dev_priv, crtc->plane);
3275 I915_WRITE(IPS_CTL, 0);
3276
3277 /* We need to wait for a vblank before we can disable the plane. */
3278 intel_wait_for_vblank(dev, crtc->pipe);
3279}
3280
3245static void haswell_crtc_enable(struct drm_crtc *crtc) 3281static void haswell_crtc_enable(struct drm_crtc *crtc)
3246{ 3282{
3247 struct drm_device *dev = crtc->dev; 3283 struct drm_device *dev = crtc->dev;
@@ -3289,6 +3325,8 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
3289 intel_crtc->config.has_pch_encoder); 3325 intel_crtc->config.has_pch_encoder);
3290 intel_enable_plane(dev_priv, plane, pipe); 3326 intel_enable_plane(dev_priv, plane, pipe);
3291 3327
3328 hsw_enable_ips(intel_crtc);
3329
3292 if (intel_crtc->config.has_pch_encoder) 3330 if (intel_crtc->config.has_pch_encoder)
3293 lpt_pch_enable(crtc); 3331 lpt_pch_enable(crtc);
3294 3332
@@ -3431,6 +3469,8 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
3431 if (dev_priv->cfb_plane == plane) 3469 if (dev_priv->cfb_plane == plane)
3432 intel_disable_fbc(dev); 3470 intel_disable_fbc(dev);
3433 3471
3472 hsw_disable_ips(intel_crtc);
3473
3434 intel_disable_plane(dev_priv, plane, pipe); 3474 intel_disable_plane(dev_priv, plane, pipe);
3435 3475
3436 if (intel_crtc->config.has_pch_encoder) 3476 if (intel_crtc->config.has_pch_encoder)
@@ -3991,11 +4031,19 @@ retry:
3991 return setup_ok ? 0 : -EINVAL; 4031 return setup_ok ? 0 : -EINVAL;
3992} 4032}
3993 4033
4034static void hsw_compute_ips_config(struct intel_crtc *crtc,
4035 struct intel_crtc_config *pipe_config)
4036{
4037 pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
4038 pipe_config->pipe_bpp == 24;
4039}
4040
3994static int intel_crtc_compute_config(struct drm_crtc *crtc, 4041static int intel_crtc_compute_config(struct drm_crtc *crtc,
3995 struct intel_crtc_config *pipe_config) 4042 struct intel_crtc_config *pipe_config)
3996{ 4043{
3997 struct drm_device *dev = crtc->dev; 4044 struct drm_device *dev = crtc->dev;
3998 struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; 4045 struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
4046 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
3999 4047
4000 if (HAS_PCH_SPLIT(dev)) { 4048 if (HAS_PCH_SPLIT(dev)) {
4001 /* FDI link clock is fixed at 2.7G */ 4049 /* FDI link clock is fixed at 2.7G */
@@ -4025,8 +4073,11 @@ static int intel_crtc_compute_config(struct drm_crtc *crtc,
4025 pipe_config->pipe_bpp = 8*3; 4073 pipe_config->pipe_bpp = 8*3;
4026 } 4074 }
4027 4075
4076 if (IS_HASWELL(dev))
4077 hsw_compute_ips_config(intel_crtc, pipe_config);
4078
4028 if (pipe_config->has_pch_encoder) 4079 if (pipe_config->has_pch_encoder)
4029 return ironlake_fdi_compute_config(to_intel_crtc(crtc), pipe_config); 4080 return ironlake_fdi_compute_config(intel_crtc, pipe_config);
4030 4081
4031 return 0; 4082 return 0;
4032} 4083}
@@ -5932,6 +5983,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
5932 if (intel_display_power_enabled(dev, pfit_domain)) 5983 if (intel_display_power_enabled(dev, pfit_domain))
5933 ironlake_get_pfit_config(crtc, pipe_config); 5984 ironlake_get_pfit_config(crtc, pipe_config);
5934 5985
5986 pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
5987 (I915_READ(IPS_CTL) & IPS_ENABLE);
5988
5935 return true; 5989 return true;
5936} 5990}
5937 5991
@@ -6236,8 +6290,10 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
6236 struct drm_device *dev = crtc->dev; 6290 struct drm_device *dev = crtc->dev;
6237 struct drm_i915_private *dev_priv = dev->dev_private; 6291 struct drm_i915_private *dev_priv = dev->dev_private;
6238 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 6292 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
6239 int palreg = PALETTE(intel_crtc->pipe); 6293 enum pipe pipe = intel_crtc->pipe;
6294 int palreg = PALETTE(pipe);
6240 int i; 6295 int i;
6296 bool reenable_ips = false;
6241 6297
6242 /* The clocks have to be on to load the palette. */ 6298 /* The clocks have to be on to load the palette. */
6243 if (!crtc->enabled || !intel_crtc->active) 6299 if (!crtc->enabled || !intel_crtc->active)
@@ -6245,7 +6301,17 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
6245 6301
6246 /* use legacy palette for Ironlake */ 6302 /* use legacy palette for Ironlake */
6247 if (HAS_PCH_SPLIT(dev)) 6303 if (HAS_PCH_SPLIT(dev))
6248 palreg = LGC_PALETTE(intel_crtc->pipe); 6304 palreg = LGC_PALETTE(pipe);
6305
6306 /* Workaround : Do not read or write the pipe palette/gamma data while
6307 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
6308 */
6309 if (intel_crtc->config.ips_enabled &&
6310 ((I915_READ(GAMMA_MODE(pipe)) & GAMMA_MODE_MODE_MASK) ==
6311 GAMMA_MODE_MODE_SPLIT)) {
6312 hsw_disable_ips(intel_crtc);
6313 reenable_ips = true;
6314 }
6249 6315
6250 for (i = 0; i < 256; i++) { 6316 for (i = 0; i < 256; i++) {
6251 I915_WRITE(palreg + 4 * i, 6317 I915_WRITE(palreg + 4 * i,
@@ -6253,6 +6319,9 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
6253 (intel_crtc->lut_g[i] << 8) | 6319 (intel_crtc->lut_g[i] << 8) |
6254 intel_crtc->lut_b[i]); 6320 intel_crtc->lut_b[i]);
6255 } 6321 }
6322
6323 if (reenable_ips)
6324 hsw_enable_ips(intel_crtc);
6256} 6325}
6257 6326
6258static void i845_update_cursor(struct drm_crtc *crtc, u32 base) 6327static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
@@ -7680,6 +7749,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
7680 DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x\n", 7749 DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x\n",
7681 pipe_config->pch_pfit.pos, 7750 pipe_config->pch_pfit.pos,
7682 pipe_config->pch_pfit.size); 7751 pipe_config->pch_pfit.size);
7752 DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
7683} 7753}
7684 7754
7685static struct intel_crtc_config * 7755static struct intel_crtc_config *
@@ -7996,6 +8066,8 @@ intel_pipe_config_compare(struct drm_device *dev,
7996 PIPE_CONF_CHECK_I(pch_pfit.pos); 8066 PIPE_CONF_CHECK_I(pch_pfit.pos);
7997 PIPE_CONF_CHECK_I(pch_pfit.size); 8067 PIPE_CONF_CHECK_I(pch_pfit.size);
7998 8068
8069 PIPE_CONF_CHECK_I(ips_enabled);
8070
7999#undef PIPE_CONF_CHECK_I 8071#undef PIPE_CONF_CHECK_I
8000#undef PIPE_CONF_CHECK_FLAGS 8072#undef PIPE_CONF_CHECK_FLAGS
8001 8073
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index bb4c50b57085..fdf6303be0a9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -268,6 +268,8 @@ struct intel_crtc_config {
268 /* FDI configuration, only valid if has_pch_encoder is set. */ 268 /* FDI configuration, only valid if has_pch_encoder is set. */
269 int fdi_lanes; 269 int fdi_lanes;
270 struct intel_link_m_n fdi_m_n; 270 struct intel_link_m_n fdi_m_n;
271
272 bool ips_enabled;
271}; 273};
272 274
273struct intel_crtc { 275struct intel_crtc {