From 46ba614c0045b0b5354397010578e8b56d621251 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 10 Sep 2013 11:40:40 +0300 Subject: drm/i915: Pass crtc to intel_update_watermarks() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Passing the appropriate crtc to intel_update_watermarks() should help in avoiding needless work in the future. v2: Avoid clash with internal 'crtc' variable in some wm functions Reviewed-by: Paulo Zanoni Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0c115cc4899..77dfd1414ef 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1087,8 +1087,9 @@ static struct drm_crtc *single_enabled_crtc(struct drm_device *dev) return enabled; } -static void pineview_update_wm(struct drm_device *dev) +static void pineview_update_wm(struct drm_crtc *unused_crtc) { + struct drm_device *dev = unused_crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; const struct cxsr_latency *latency; @@ -1365,8 +1366,9 @@ static void vlv_update_drain_latency(struct drm_device *dev) #define single_plane_enabled(mask) is_power_of_2(mask) -static void valleyview_update_wm(struct drm_device *dev) +static void valleyview_update_wm(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; static const int sr_latency_ns = 12000; struct drm_i915_private *dev_priv = dev->dev_private; int planea_wm, planeb_wm, cursora_wm, cursorb_wm; @@ -1424,8 +1426,9 @@ static void valleyview_update_wm(struct drm_device *dev) (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); } -static void g4x_update_wm(struct drm_device *dev) +static void g4x_update_wm(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; static const int sr_latency_ns = 12000; struct drm_i915_private *dev_priv = dev->dev_private; int planea_wm, planeb_wm, cursora_wm, cursorb_wm; @@ -1476,8 +1479,9 @@ static void g4x_update_wm(struct drm_device *dev) (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); } -static void i965_update_wm(struct drm_device *dev) +static void i965_update_wm(struct drm_crtc *unused_crtc) { + struct drm_device *dev = unused_crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; int srwm = 1; @@ -1541,8 +1545,9 @@ static void i965_update_wm(struct drm_device *dev) I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT)); } -static void i9xx_update_wm(struct drm_device *dev) +static void i9xx_update_wm(struct drm_crtc *unused_crtc) { + struct drm_device *dev = unused_crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; const struct intel_watermark_params *wm_info; uint32_t fwater_lo; @@ -1658,8 +1663,9 @@ static void i9xx_update_wm(struct drm_device *dev) } } -static void i830_update_wm(struct drm_device *dev) +static void i830_update_wm(struct drm_crtc *unused_crtc) { + struct drm_device *dev = unused_crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; uint32_t fwater_lo; @@ -1785,8 +1791,9 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, display, cursor); } -static void ironlake_update_wm(struct drm_device *dev) +static void ironlake_update_wm(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; int fbc_wm, plane_wm, cursor_wm; unsigned int enabled; @@ -1868,8 +1875,9 @@ static void ironlake_update_wm(struct drm_device *dev) */ } -static void sandybridge_update_wm(struct drm_device *dev) +static void sandybridge_update_wm(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; int latency = dev_priv->wm.pri_latency[0] * 100; /* In unit 0.1us */ u32 val; @@ -1970,8 +1978,9 @@ static void sandybridge_update_wm(struct drm_device *dev) cursor_wm); } -static void ivybridge_update_wm(struct drm_device *dev) +static void ivybridge_update_wm(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; int latency = dev_priv->wm.pri_latency[0] * 100; /* In unit 0.1us */ u32 val; @@ -2841,8 +2850,9 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, I915_WRITE(WM3_LP_ILK, results->wm_lp[2]); } -static void haswell_update_wm(struct drm_device *dev) +static void haswell_update_wm(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct hsw_wm_maximums lp_max_1_2, lp_max_5_6; struct hsw_pipe_wm_parameters params[3]; @@ -2879,7 +2889,7 @@ static void haswell_update_sprite_wm(struct drm_plane *plane, intel_plane->wm.horiz_pixels = sprite_width; intel_plane->wm.bytes_per_pixel = pixel_size; - haswell_update_wm(plane->dev); + haswell_update_wm(crtc); } static bool @@ -3076,12 +3086,12 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane, * We don't use the sprite, so we can ignore that. And on Crestline we have * to set the non-SR watermarks to 8. */ -void intel_update_watermarks(struct drm_device *dev) +void intel_update_watermarks(struct drm_crtc *crtc) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_private *dev_priv = crtc->dev->dev_private; if (dev_priv->display.update_wm) - dev_priv->display.update_wm(dev); + dev_priv->display.update_wm(crtc); } void intel_update_sprite_watermarks(struct drm_plane *plane, -- cgit v1.2.3-70-g09d2 From ac830fe1c3d811db2bef1835b6e0c693bc3b237e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 30 Aug 2013 14:30:23 +0300 Subject: drm/i915: Constify some watermark data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hsw_pipe_wm_parameters and hsw_wm_maximums typically are read only. Make them const. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 77dfd1414ef..3dd2fd859fb 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2205,7 +2205,7 @@ struct intel_wm_config { * For both WM_PIPE and WM_LP. * mem_value must be in 0.1us units. */ -static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params, +static uint32_t ilk_compute_pri_wm(const struct hsw_pipe_wm_parameters *params, uint32_t mem_value, bool is_lp) { @@ -2234,7 +2234,7 @@ static uint32_t ilk_compute_pri_wm(struct hsw_pipe_wm_parameters *params, * For both WM_PIPE and WM_LP. * mem_value must be in 0.1us units. */ -static uint32_t ilk_compute_spr_wm(struct hsw_pipe_wm_parameters *params, +static uint32_t ilk_compute_spr_wm(const struct hsw_pipe_wm_parameters *params, uint32_t mem_value) { uint32_t method1, method2; @@ -2257,7 +2257,7 @@ static uint32_t ilk_compute_spr_wm(struct hsw_pipe_wm_parameters *params, * For both WM_PIPE and WM_LP. * mem_value must be in 0.1us units. */ -static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params, +static uint32_t ilk_compute_cur_wm(const struct hsw_pipe_wm_parameters *params, uint32_t mem_value) { if (!params->active || !params->cur.enabled) @@ -2271,7 +2271,7 @@ static uint32_t ilk_compute_cur_wm(struct hsw_pipe_wm_parameters *params, } /* Only for WM_LP. */ -static uint32_t ilk_compute_fbc_wm(struct hsw_pipe_wm_parameters *params, +static uint32_t ilk_compute_fbc_wm(const struct hsw_pipe_wm_parameters *params, uint32_t pri_val) { if (!params->active || !params->pri.enabled) @@ -2422,7 +2422,7 @@ static bool ilk_check_wm(int level, static void ilk_compute_wm_level(struct drm_i915_private *dev_priv, int level, - struct hsw_pipe_wm_parameters *p, + const struct hsw_pipe_wm_parameters *p, struct intel_wm_level *result) { uint16_t pri_latency = dev_priv->wm.pri_latency[level]; @@ -2444,8 +2444,8 @@ static void ilk_compute_wm_level(struct drm_i915_private *dev_priv, } static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv, - int level, struct hsw_wm_maximums *max, - struct hsw_pipe_wm_parameters *params, + int level, const struct hsw_wm_maximums *max, + const struct hsw_pipe_wm_parameters *params, struct intel_wm_level *result) { enum pipe pipe; @@ -2465,7 +2465,7 @@ static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv, static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, - struct hsw_pipe_wm_parameters *params) + const struct hsw_pipe_wm_parameters *params) { uint32_t pri_val, cur_val, spr_val; /* WM0 latency values stored in 0.1us units */ @@ -2673,8 +2673,8 @@ static void hsw_compute_wm_parameters(struct drm_device *dev, } static void hsw_compute_wm_results(struct drm_device *dev, - struct hsw_pipe_wm_parameters *params, - struct hsw_wm_maximums *lp_maximums, + const struct hsw_pipe_wm_parameters *params, + const struct hsw_wm_maximums *lp_maximums, struct hsw_wm_values *results) { struct drm_i915_private *dev_priv = dev->dev_private; -- cgit v1.2.3-70-g09d2 From 8de123a5d89f8eaf934737758251fb18b2660231 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 30 Aug 2013 14:30:24 +0300 Subject: drm/i915: Use ilk_compute_wm_level to compute WM_PIPE values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify the code a bit to use ilk_compute_wm_level for all watermark levels. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 44 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 23 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3dd2fd859fb..865d524f1e8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2463,33 +2463,31 @@ static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv, return ilk_check_wm(level, max, result); } -static uint32_t hsw_compute_wm_pipe(struct drm_i915_private *dev_priv, - enum pipe pipe, + +static uint32_t hsw_compute_wm_pipe(struct drm_device *dev, const struct hsw_pipe_wm_parameters *params) { - uint32_t pri_val, cur_val, spr_val; - /* WM0 latency values stored in 0.1us units */ - uint16_t pri_latency = dev_priv->wm.pri_latency[0]; - uint16_t spr_latency = dev_priv->wm.spr_latency[0]; - uint16_t cur_latency = dev_priv->wm.cur_latency[0]; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_wm_config config = { + .num_pipes_active = 1, + .sprites_enabled = params->spr.enabled, + .sprites_scaled = params->spr.scaled, + }; + struct hsw_wm_maximums max; + struct intel_wm_level res; + + if (!params->active) + return 0; + + ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max); - pri_val = ilk_compute_pri_wm(params, pri_latency, false); - spr_val = ilk_compute_spr_wm(params, spr_latency); - cur_val = ilk_compute_cur_wm(params, cur_latency); + ilk_compute_wm_level(dev_priv, 0, params, &res); - WARN(pri_val > 127, - "Primary WM error, mode not supported for pipe %c\n", - pipe_name(pipe)); - WARN(spr_val > 127, - "Sprite WM error, mode not supported for pipe %c\n", - pipe_name(pipe)); - WARN(cur_val > 63, - "Cursor WM error, mode not supported for pipe %c\n", - pipe_name(pipe)); + ilk_check_wm(0, &max, &res); - return (pri_val << WM0_PIPE_PLANE_SHIFT) | - (spr_val << WM0_PIPE_SPRITE_SHIFT) | - cur_val; + return (res.pri_val << WM0_PIPE_PLANE_SHIFT) | + (res.spr_val << WM0_PIPE_SPRITE_SHIFT) | + res.cur_val; } static uint32_t @@ -2718,7 +2716,7 @@ static void hsw_compute_wm_results(struct drm_device *dev, } for_each_pipe(pipe) - results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev_priv, pipe, + results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev, ¶ms[pipe]); for_each_pipe(pipe) { -- cgit v1.2.3-70-g09d2 From ad0d6dc4859ffb769768b64942b6a110e92acd21 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 30 Aug 2013 14:30:25 +0300 Subject: drm/i915: Refactor max WM level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the expected max WM level determinations out to a separate function. Will have another user soon. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 865d524f1e8..c1b601aacc3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2561,19 +2561,22 @@ static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5]) wm[3] *= 2; } -static void intel_print_wm_latency(struct drm_device *dev, - const char *name, - const uint16_t wm[5]) +static int ilk_wm_max_level(const struct drm_device *dev) { - int level, max_level; - /* how many WM levels are we expecting */ if (IS_HASWELL(dev)) - max_level = 4; + return 4; else if (INTEL_INFO(dev)->gen >= 6) - max_level = 3; + return 3; else - max_level = 2; + return 2; +} + +static void intel_print_wm_latency(struct drm_device *dev, + const char *name, + const uint16_t wm[5]) +{ + int level, max_level = ilk_wm_max_level(dev); for (level = 0; level <= max_level; level++) { unsigned int latency = wm[level]; -- cgit v1.2.3-70-g09d2 From ef644fdac1709b91a8c7df546c6d597388f17a1b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 4 Sep 2013 18:25:21 +0300 Subject: drm/i915: Use adjusted_mode in intel_update_fbc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check the mode flags from the adjusted_mode, not user requested mode. The hdisplay/vdisplay check actually checkes the primary plane size, so those still need to come from the user requested mode. Extract both modes from pipe config instead of the drm_crtc. Signed-off-by: Ville Syrjälä Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index c1b601aacc3..e5f7e56b7c4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -458,6 +458,8 @@ void intel_update_fbc(struct drm_device *dev) struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; struct drm_i915_gem_object *obj; + const struct drm_display_mode *mode; + const struct drm_display_mode *adjusted_mode; unsigned int max_hdisplay, max_vdisplay; if (!I915_HAS_FBC(dev)) { @@ -502,6 +504,8 @@ void intel_update_fbc(struct drm_device *dev) fb = crtc->fb; intel_fb = to_intel_framebuffer(fb); obj = intel_fb->obj; + mode = &intel_crtc->config.requested_mode; + adjusted_mode = &intel_crtc->config.adjusted_mode; if (i915_enable_fbc < 0 && INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev)) { @@ -514,8 +518,8 @@ void intel_update_fbc(struct drm_device *dev) DRM_DEBUG_KMS("fbc disabled per module param\n"); goto out_disable; } - if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) || - (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) { + if ((adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) || + (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)) { if (set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED_MODE)) DRM_DEBUG_KMS("mode incompatible with compression, " "disabling\n"); @@ -529,8 +533,8 @@ void intel_update_fbc(struct drm_device *dev) max_hdisplay = 2048; max_vdisplay = 1536; } - if ((crtc->mode.hdisplay > max_hdisplay) || - (crtc->mode.vdisplay > max_vdisplay)) { + if ((mode->hdisplay > max_hdisplay) || + (mode->vdisplay > max_vdisplay)) { if (set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE)) DRM_DEBUG_KMS("mode too large for compression, disabling\n"); goto out_disable; -- cgit v1.2.3-70-g09d2 From 4fe8590a921d0b2e36e542dbfa89a8c5993f5a3f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 4 Sep 2013 18:25:22 +0300 Subject: drm/i915: Use adjusted_mode appropriately when computing watermarks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently most of the watermark code looks at crtc->mode which is the user requested mode. The only piece of information there that is relevant is hdisplay, the rest must come from adjusted_mode. Convert all of the code to use requested_mode and adjusted_mode from pipe config appropriately. Signed-off-by: Ville Syrjälä Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 55 ++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e5f7e56b7c4..527bc41c9b8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1110,7 +1110,7 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc) crtc = single_enabled_crtc(dev); if (crtc) { - int clock = crtc->mode.clock; + int clock = to_intel_crtc(crtc)->config.adjusted_mode.clock; int pixel_size = crtc->fb->bits_per_pixel / 8; /* Display SR */ @@ -1171,6 +1171,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, int *cursor_wm) { struct drm_crtc *crtc; + const struct drm_display_mode *adjusted_mode; int htotal, hdisplay, clock, pixel_size; int line_time_us, line_count; int entries, tlb_miss; @@ -1182,9 +1183,10 @@ static bool g4x_compute_wm0(struct drm_device *dev, return false; } - htotal = crtc->mode.htotal; - hdisplay = crtc->mode.hdisplay; - clock = crtc->mode.clock; + adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; + clock = adjusted_mode->clock; + htotal = adjusted_mode->htotal; + hdisplay = to_intel_crtc(crtc)->config.requested_mode.hdisplay; pixel_size = crtc->fb->bits_per_pixel / 8; /* Use the small buffer method to calculate plane watermark */ @@ -1255,6 +1257,7 @@ static bool g4x_compute_srwm(struct drm_device *dev, int *display_wm, int *cursor_wm) { struct drm_crtc *crtc; + const struct drm_display_mode *adjusted_mode; int hdisplay, htotal, pixel_size, clock; unsigned long line_time_us; int line_count, line_size; @@ -1267,9 +1270,10 @@ static bool g4x_compute_srwm(struct drm_device *dev, } crtc = intel_get_crtc_for_plane(dev, plane); - hdisplay = crtc->mode.hdisplay; - htotal = crtc->mode.htotal; - clock = crtc->mode.clock; + adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; + clock = adjusted_mode->clock; + htotal = adjusted_mode->htotal; + hdisplay = to_intel_crtc(crtc)->config.requested_mode.hdisplay; pixel_size = crtc->fb->bits_per_pixel / 8; line_time_us = (htotal * 1000) / clock; @@ -1308,7 +1312,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, if (!intel_crtc_active(crtc)) return false; - clock = crtc->mode.clock; /* VESA DOT Clock */ + clock = to_intel_crtc(crtc)->config.adjusted_mode.clock; pixel_size = crtc->fb->bits_per_pixel / 8; /* BPP */ entries = (clock / 1000) * pixel_size; @@ -1496,9 +1500,11 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) if (crtc) { /* self-refresh has much higher latency */ static const int sr_latency_ns = 12000; - int clock = crtc->mode.clock; - int htotal = crtc->mode.htotal; - int hdisplay = crtc->mode.hdisplay; + const struct drm_display_mode *adjusted_mode = + &to_intel_crtc(crtc)->config.adjusted_mode; + int clock = adjusted_mode->clock; + int htotal = adjusted_mode->htotal; + int hdisplay = to_intel_crtc(crtc)->config.requested_mode.hdisplay; int pixel_size = crtc->fb->bits_per_pixel / 8; unsigned long line_time_us; int entries; @@ -1575,7 +1581,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) if (IS_GEN2(dev)) cpp = 4; - planea_wm = intel_calculate_wm(crtc->mode.clock, + planea_wm = intel_calculate_wm(to_intel_crtc(crtc)->config.adjusted_mode.clock, wm_info, fifo_size, cpp, latency_ns); enabled = crtc; @@ -1589,7 +1595,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) if (IS_GEN2(dev)) cpp = 4; - planeb_wm = intel_calculate_wm(crtc->mode.clock, + planeb_wm = intel_calculate_wm(to_intel_crtc(crtc)->config.adjusted_mode.clock, wm_info, fifo_size, cpp, latency_ns); if (enabled == NULL) @@ -1616,9 +1622,11 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) if (HAS_FW_BLC(dev) && enabled) { /* self-refresh has much higher latency */ static const int sr_latency_ns = 6000; - int clock = enabled->mode.clock; - int htotal = enabled->mode.htotal; - int hdisplay = enabled->mode.hdisplay; + const struct drm_display_mode *adjusted_mode = + &to_intel_crtc(enabled)->config.adjusted_mode; + int clock = adjusted_mode->clock; + int htotal = adjusted_mode->htotal; + int hdisplay = to_intel_crtc(crtc)->config.requested_mode.hdisplay; int pixel_size = enabled->fb->bits_per_pixel / 8; unsigned long line_time_us; int entries; @@ -1679,7 +1687,8 @@ static void i830_update_wm(struct drm_crtc *unused_crtc) if (crtc == NULL) return; - planea_wm = intel_calculate_wm(crtc->mode.clock, &i830_wm_info, + planea_wm = intel_calculate_wm(to_intel_crtc(crtc)->config.adjusted_mode.clock, + &i830_wm_info, dev_priv->display.get_fifo_size(dev, 0), 4, latency_ns); fwater_lo = I915_READ(FW_BLC) & ~0xfff; @@ -1751,6 +1760,7 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, int *fbc_wm, int *display_wm, int *cursor_wm) { struct drm_crtc *crtc; + const struct drm_display_mode *adjusted_mode; unsigned long line_time_us; int hdisplay, htotal, pixel_size, clock; int line_count, line_size; @@ -1763,9 +1773,10 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, } crtc = intel_get_crtc_for_plane(dev, plane); - hdisplay = crtc->mode.hdisplay; - htotal = crtc->mode.htotal; - clock = crtc->mode.clock; + adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; + clock = adjusted_mode->clock; + htotal = adjusted_mode->htotal; + hdisplay = to_intel_crtc(crtc)->config.requested_mode.hdisplay; pixel_size = crtc->fb->bits_per_pixel / 8; line_time_us = (htotal * 1000) / clock; @@ -2913,7 +2924,7 @@ sandybridge_compute_sprite_wm(struct drm_device *dev, int plane, return false; } - clock = crtc->mode.clock; + clock = to_intel_crtc(crtc)->config.adjusted_mode.clock; /* Use the small buffer method to calculate the sprite watermark */ entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; @@ -2948,7 +2959,7 @@ sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane, } crtc = intel_get_crtc_for_plane(dev, plane); - clock = crtc->mode.clock; + clock = to_intel_crtc(crtc)->config.adjusted_mode.clock; if (!clock) { *sprite_wm = 0; return false; -- cgit v1.2.3-70-g09d2 From 4af67d41c8e321fc1341fc9e3f07e7813628084a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 4 Sep 2013 18:25:23 +0300 Subject: drm/i915: Check the clock from adjusted mode in intel_crtc_active() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The clock in crtc->mode doesn't necessarily mean anything. Let's look at the clock in adjusted_mode instead. Signed-off-by: Ville Syrjälä Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 527bc41c9b8..4016ca8d151 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -45,10 +45,13 @@ static bool intel_crtc_active(struct drm_crtc *crtc) { + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + /* Be paranoid as we can arrive here with only partial * state retrieved from the hardware during setup. */ - return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock; + return intel_crtc->active && crtc->fb && + intel_crtc->config.adjusted_mode.clock; } static void i8xx_disable_fbc(struct drm_device *dev) -- cgit v1.2.3-70-g09d2 From 20ddf6650458d08d42c3c3f8240a0d00a7e9ee97 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 4 Sep 2013 18:25:25 +0300 Subject: drm/i915: Make intel_crtc_active() available outside intel_pm.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move intel_crtc_active() to intel_display.c and make it available elsewhere as well. intel_edp_psr_match_conditions() already has one open coded copy, so replace that one with a call to intel_crtc_active(). v2: Copy paste a big comment from danvet's mail explaining when we can ditch the extra checks Signed-off-by: Ville Syrjälä Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 3 +-- drivers/gpu/drm/i915/intel_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 11 ----------- 4 files changed, 20 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8b5fa95f947..234a77d0ee4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -733,6 +733,23 @@ vlv_find_best_dpll(const intel_limit_t *limit, struct drm_crtc *crtc, return true; } +bool intel_crtc_active(struct drm_crtc *crtc) +{ + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + /* Be paranoid as we can arrive here with only partial + * state retrieved from the hardware during setup. + * + * We can ditch the adjusted_mode.clock check as soon + * as Haswell has gained clock readout/fastboot support. + * + * We can ditch the crtc->fb check as soon as we can + * properly reconstruct framebuffers. + */ + return intel_crtc->active && crtc->fb && + intel_crtc->config.adjusted_mode.clock; +} + enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, enum pipe pipe) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 0d9372e75f6..e61ba90fb1b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1628,8 +1628,7 @@ static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp) } intel_crtc = to_intel_crtc(crtc); - if (!intel_crtc->active || !crtc->fb || - !intel_crtc->config.adjusted_mode.clock) { + if (!intel_crtc_active(crtc)) { DRM_DEBUG_KMS("crtc not active for PSR\n"); dev_priv->no_psr_reason = PSR_CRTC_NOT_ACTIVE; return false; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e87ba822deb..8306940f0ae 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -808,4 +808,6 @@ extern int intel_dotclock_calculate(int link_freq, extern void ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config, int dotclock); +extern bool intel_crtc_active(struct drm_crtc *crtc); + #endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4016ca8d151..9cf3aa52541 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -43,17 +43,6 @@ * i915.i915_enable_fbc parameter */ -static bool intel_crtc_active(struct drm_crtc *crtc) -{ - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - - /* Be paranoid as we can arrive here with only partial - * state retrieved from the hardware during setup. - */ - return intel_crtc->active && crtc->fb && - intel_crtc->config.adjusted_mode.clock; -} - static void i8xx_disable_fbc(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; -- cgit v1.2.3-70-g09d2 From 37327abdfbb4e2d7c9033f450de5e36e401d6efc Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 4 Sep 2013 18:25:28 +0300 Subject: drm/i915: Add explicit pipe src size to pipe config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather that mess about with hdisplay/vdisplay from requested_mode, add explicit pipe src size information to pipe config. Now requested_mode is only really relevant for dvo/sdvo output timings. For everything else either adjusted_mode or pipe src size should be used. In many places where we end up using pipe source size, we should actually use the primary plane size, but we don't currently store that information explicitly. As long as we treat primaries as full screen only, we can get away with this. Eventually when we move primaries over to drm_plane, we need to fix it all up. v2: Add a comment to explain what pipe_src_{w,h} are Add a note about primary planes to commit message Signed-off-by: Ville Syrjälä Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 26 +++++++++++------ drivers/gpu/drm/i915/intel_drv.h | 6 ++++ drivers/gpu/drm/i915/intel_panel.c | 56 +++++++++++++++++------------------- drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++----------- drivers/gpu/drm/i915/intel_sprite.c | 4 +-- 5 files changed, 67 insertions(+), 58 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 234a77d0ee4..b8d7ad6cab9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4696,7 +4696,6 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc) enum transcoder cpu_transcoder = intel_crtc->config.cpu_transcoder; struct drm_display_mode *adjusted_mode = &intel_crtc->config.adjusted_mode; - struct drm_display_mode *mode = &intel_crtc->config.requested_mode; uint32_t vsyncshift, crtc_vtotal, crtc_vblank_end; /* We need to be careful not to changed the adjusted mode, for otherwise @@ -4749,7 +4748,8 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc) * always be the user's requested size. */ I915_WRITE(PIPESRC(pipe), - ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); + ((intel_crtc->config.pipe_src_w - 1) << 16) | + (intel_crtc->config.pipe_src_h - 1)); } static void intel_get_pipe_timings(struct intel_crtc *crtc, @@ -4787,8 +4787,11 @@ static void intel_get_pipe_timings(struct intel_crtc *crtc, } tmp = I915_READ(PIPESRC(crtc->pipe)); - pipe_config->requested_mode.vdisplay = (tmp & 0xffff) + 1; - pipe_config->requested_mode.hdisplay = ((tmp >> 16) & 0xffff) + 1; + pipe_config->pipe_src_h = (tmp & 0xffff) + 1; + pipe_config->pipe_src_w = ((tmp >> 16) & 0xffff) + 1; + + pipe_config->requested_mode.vdisplay = pipe_config->pipe_src_h; + pipe_config->requested_mode.hdisplay = pipe_config->pipe_src_w; } static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc, @@ -4884,7 +4887,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_display_mode *mode = &intel_crtc->config.requested_mode; int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; int refclk, num_connectors = 0; @@ -4983,8 +4985,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, * which should always be the user's requested size. */ I915_WRITE(DSPSIZE(plane), - ((mode->vdisplay - 1) << 16) | - (mode->hdisplay - 1)); + ((intel_crtc->config.pipe_src_h - 1) << 16) | + (intel_crtc->config.pipe_src_w - 1)); I915_WRITE(DSPPOS(plane), 0); i9xx_set_pipeconf(intel_crtc); @@ -8349,6 +8351,8 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, DRM_DEBUG_KMS("adjusted mode:\n"); drm_mode_debug_printmodeline(&pipe_config->adjusted_mode); DRM_DEBUG_KMS("port clock: %d\n", pipe_config->port_clock); + DRM_DEBUG_KMS("pipe src size: %dx%d\n", + pipe_config->pipe_src_w, pipe_config->pipe_src_h); DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n", pipe_config->gmch_pfit.control, pipe_config->gmch_pfit.pgm_ratios, @@ -8400,6 +8404,10 @@ intel_modeset_pipe_config(struct drm_crtc *crtc, drm_mode_copy(&pipe_config->adjusted_mode, mode); drm_mode_copy(&pipe_config->requested_mode, mode); + + pipe_config->pipe_src_w = mode->hdisplay; + pipe_config->pipe_src_h = mode->vdisplay; + pipe_config->cpu_transcoder = (enum transcoder) to_intel_crtc(crtc)->pipe; pipe_config->shared_dpll = DPLL_ID_PRIVATE; @@ -8756,8 +8764,8 @@ intel_pipe_config_compare(struct drm_device *dev, DRM_MODE_FLAG_NVSYNC); } - PIPE_CONF_CHECK_I(requested_mode.hdisplay); - PIPE_CONF_CHECK_I(requested_mode.vdisplay); + PIPE_CONF_CHECK_I(pipe_src_w); + PIPE_CONF_CHECK_I(pipe_src_h); PIPE_CONF_CHECK_I(gmch_pfit.control); /* pfit ratios are autocomputed by the hw on gen4+ */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8306940f0ae..3046e78f31e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -215,6 +215,12 @@ struct intel_crtc_config { /* Actual pipe timings ie. what we program into the pipe timing * registers. adjusted_mode.clock is the pipe pixel clock. */ struct drm_display_mode adjusted_mode; + + /* Pipe source size (ie. panel fitter input size) + * All planes will be positioned inside this space, + * and get clipped at the edges. */ + int pipe_src_w, pipe_src_h; + /* Whether to set up the PCH/FDI. Note that we never allow sharing * between pch encoders and cpu encoders. */ bool has_pch_encoder; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 42114ecbae0..c9dba46f52a 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -50,23 +50,22 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc, struct intel_crtc_config *pipe_config, int fitting_mode) { - struct drm_display_mode *mode, *adjusted_mode; + struct drm_display_mode *adjusted_mode; int x, y, width, height; - mode = &pipe_config->requested_mode; adjusted_mode = &pipe_config->adjusted_mode; x = y = width = height = 0; /* Native modes don't need fitting */ - if (adjusted_mode->hdisplay == mode->hdisplay && - adjusted_mode->vdisplay == mode->vdisplay) + if (adjusted_mode->hdisplay == pipe_config->pipe_src_w && + adjusted_mode->vdisplay == pipe_config->pipe_src_h) goto done; switch (fitting_mode) { case DRM_MODE_SCALE_CENTER: - width = mode->hdisplay; - height = mode->vdisplay; + width = pipe_config->pipe_src_w; + height = pipe_config->pipe_src_h; x = (adjusted_mode->hdisplay - width + 1)/2; y = (adjusted_mode->vdisplay - height + 1)/2; break; @@ -74,17 +73,17 @@ intel_pch_panel_fitting(struct intel_crtc *intel_crtc, case DRM_MODE_SCALE_ASPECT: /* Scale but preserve the aspect ratio */ { - u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; - u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; + u32 scaled_width = adjusted_mode->hdisplay * pipe_config->pipe_src_h; + u32 scaled_height = pipe_config->pipe_src_w * adjusted_mode->vdisplay; if (scaled_width > scaled_height) { /* pillar */ - width = scaled_height / mode->vdisplay; + width = scaled_height / pipe_config->pipe_src_h; if (width & 1) width++; x = (adjusted_mode->hdisplay - width + 1) / 2; y = 0; height = adjusted_mode->vdisplay; } else if (scaled_width < scaled_height) { /* letter */ - height = scaled_width / mode->hdisplay; + height = scaled_width / pipe_config->pipe_src_w; if (height & 1) height++; y = (adjusted_mode->vdisplay - height + 1) / 2; @@ -176,14 +175,13 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, { struct drm_device *dev = intel_crtc->base.dev; u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; - struct drm_display_mode *mode, *adjusted_mode; + struct drm_display_mode *adjusted_mode; - mode = &pipe_config->requested_mode; adjusted_mode = &pipe_config->adjusted_mode; /* Native modes don't need fitting */ - if (adjusted_mode->hdisplay == mode->hdisplay && - adjusted_mode->vdisplay == mode->vdisplay) + if (adjusted_mode->hdisplay == pipe_config->pipe_src_w && + adjusted_mode->vdisplay == pipe_config->pipe_src_h) goto out; switch (fitting_mode) { @@ -192,16 +190,16 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, * For centered modes, we have to calculate border widths & * heights and modify the values programmed into the CRTC. */ - centre_horizontally(adjusted_mode, mode->hdisplay); - centre_vertically(adjusted_mode, mode->vdisplay); + centre_horizontally(adjusted_mode, pipe_config->pipe_src_w); + centre_vertically(adjusted_mode, pipe_config->pipe_src_h); border = LVDS_BORDER_ENABLE; break; case DRM_MODE_SCALE_ASPECT: /* Scale but preserve the aspect ratio */ if (INTEL_INFO(dev)->gen >= 4) { u32 scaled_width = adjusted_mode->hdisplay * - mode->vdisplay; - u32 scaled_height = mode->hdisplay * + pipe_config->pipe_src_h; + u32 scaled_height = pipe_config->pipe_src_w * adjusted_mode->vdisplay; /* 965+ is easy, it does everything in hw */ @@ -211,12 +209,12 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, else if (scaled_width < scaled_height) pfit_control |= PFIT_ENABLE | PFIT_SCALING_LETTER; - else if (adjusted_mode->hdisplay != mode->hdisplay) + else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w) pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; } else { u32 scaled_width = adjusted_mode->hdisplay * - mode->vdisplay; - u32 scaled_height = mode->hdisplay * + pipe_config->pipe_src_h; + u32 scaled_height = pipe_config->pipe_src_w * adjusted_mode->vdisplay; /* * For earlier chips we have to calculate the scaling @@ -226,11 +224,11 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, if (scaled_width > scaled_height) { /* pillar */ centre_horizontally(adjusted_mode, scaled_height / - mode->vdisplay); + pipe_config->pipe_src_h); border = LVDS_BORDER_ENABLE; - if (mode->vdisplay != adjusted_mode->vdisplay) { - u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay); + if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) { + u32 bits = panel_fitter_scaling(pipe_config->pipe_src_h, adjusted_mode->vdisplay); pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | bits << PFIT_VERT_SCALE_SHIFT); pfit_control |= (PFIT_ENABLE | @@ -240,11 +238,11 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, } else if (scaled_width < scaled_height) { /* letter */ centre_vertically(adjusted_mode, scaled_width / - mode->hdisplay); + pipe_config->pipe_src_w); border = LVDS_BORDER_ENABLE; - if (mode->hdisplay != adjusted_mode->hdisplay) { - u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay); + if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) { + u32 bits = panel_fitter_scaling(pipe_config->pipe_src_w, adjusted_mode->hdisplay); pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | bits << PFIT_VERT_SCALE_SHIFT); pfit_control |= (PFIT_ENABLE | @@ -265,8 +263,8 @@ void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc, * Full scaling, even if it changes the aspect ratio. * Fortunately this is all done for us in hw. */ - if (mode->vdisplay != adjusted_mode->vdisplay || - mode->hdisplay != adjusted_mode->hdisplay) { + if (pipe_config->pipe_src_h != adjusted_mode->vdisplay || + pipe_config->pipe_src_w != adjusted_mode->hdisplay) { pfit_control |= PFIT_ENABLE; if (INTEL_INFO(dev)->gen >= 4) pfit_control |= PFIT_SCALING_AUTO; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9cf3aa52541..fe19ba3360a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -450,9 +450,8 @@ void intel_update_fbc(struct drm_device *dev) struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; struct drm_i915_gem_object *obj; - const struct drm_display_mode *mode; const struct drm_display_mode *adjusted_mode; - unsigned int max_hdisplay, max_vdisplay; + unsigned int max_width, max_height; if (!I915_HAS_FBC(dev)) { set_no_fbc_reason(dev_priv, FBC_UNSUPPORTED); @@ -496,7 +495,6 @@ void intel_update_fbc(struct drm_device *dev) fb = crtc->fb; intel_fb = to_intel_framebuffer(fb); obj = intel_fb->obj; - mode = &intel_crtc->config.requested_mode; adjusted_mode = &intel_crtc->config.adjusted_mode; if (i915_enable_fbc < 0 && @@ -519,14 +517,14 @@ void intel_update_fbc(struct drm_device *dev) } if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { - max_hdisplay = 4096; - max_vdisplay = 2048; + max_width = 4096; + max_height = 2048; } else { - max_hdisplay = 2048; - max_vdisplay = 1536; + max_width = 2048; + max_height = 1536; } - if ((mode->hdisplay > max_hdisplay) || - (mode->vdisplay > max_vdisplay)) { + if (intel_crtc->config.pipe_src_w > max_width || + intel_crtc->config.pipe_src_h > max_height) { if (set_no_fbc_reason(dev_priv, FBC_MODE_TOO_LARGE)) DRM_DEBUG_KMS("mode too large for compression, disabling\n"); goto out_disable; @@ -1178,7 +1176,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; clock = adjusted_mode->clock; htotal = adjusted_mode->htotal; - hdisplay = to_intel_crtc(crtc)->config.requested_mode.hdisplay; + hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; pixel_size = crtc->fb->bits_per_pixel / 8; /* Use the small buffer method to calculate plane watermark */ @@ -1265,7 +1263,7 @@ static bool g4x_compute_srwm(struct drm_device *dev, adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; clock = adjusted_mode->clock; htotal = adjusted_mode->htotal; - hdisplay = to_intel_crtc(crtc)->config.requested_mode.hdisplay; + hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; pixel_size = crtc->fb->bits_per_pixel / 8; line_time_us = (htotal * 1000) / clock; @@ -1496,7 +1494,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) &to_intel_crtc(crtc)->config.adjusted_mode; int clock = adjusted_mode->clock; int htotal = adjusted_mode->htotal; - int hdisplay = to_intel_crtc(crtc)->config.requested_mode.hdisplay; + int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; int pixel_size = crtc->fb->bits_per_pixel / 8; unsigned long line_time_us; int entries; @@ -1618,7 +1616,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) &to_intel_crtc(enabled)->config.adjusted_mode; int clock = adjusted_mode->clock; int htotal = adjusted_mode->htotal; - int hdisplay = to_intel_crtc(crtc)->config.requested_mode.hdisplay; + int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; int pixel_size = enabled->fb->bits_per_pixel / 8; unsigned long line_time_us; int entries; @@ -1768,7 +1766,7 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; clock = adjusted_mode->clock; htotal = adjusted_mode->htotal; - hdisplay = to_intel_crtc(crtc)->config.requested_mode.hdisplay; + hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; pixel_size = crtc->fb->bits_per_pixel / 8; line_time_us = (htotal * 1000) / clock; @@ -2123,8 +2121,8 @@ static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev, if (pfit_size) { uint64_t pipe_w, pipe_h, pfit_w, pfit_h; - pipe_w = intel_crtc->config.requested_mode.hdisplay; - pipe_h = intel_crtc->config.requested_mode.vdisplay; + pipe_w = intel_crtc->config.pipe_src_w; + pipe_h = intel_crtc->config.pipe_src_h; pfit_w = (pfit_size >> 16) & 0xFFFF; pfit_h = pfit_size & 0xFFFF; if (pipe_w < pfit_w) @@ -2650,8 +2648,7 @@ static void hsw_compute_wm_parameters(struct drm_device *dev, p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc); p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8; p->cur.bytes_per_pixel = 4; - p->pri.horiz_pixels = - intel_crtc->config.requested_mode.hdisplay; + p->pri.horiz_pixels = intel_crtc->config.pipe_src_w; p->cur.horiz_pixels = 64; /* TODO: for now, assume primary and cursor planes are always enabled. */ p->pri.enabled = true; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index ae0e686e6e5..231b289e8e5 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -652,8 +652,8 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, .y2 = crtc_y + crtc_h, }; const struct drm_rect clip = { - .x2 = intel_crtc->config.requested_mode.hdisplay, - .y2 = intel_crtc->config.requested_mode.vdisplay, + .x2 = intel_crtc->config.pipe_src_w, + .y2 = intel_crtc->config.pipe_src_h, }; intel_fb = to_intel_framebuffer(fb); -- cgit v1.2.3-70-g09d2 From a2b23fe04e183ef58ed45183e39dbc696f9600b1 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 19 Sep 2013 09:33:13 -0700 Subject: drm/i915/vlv: honor i915_enable_rc6 boot param on VLV Disabling it isn't really an option on these platforms, but having it available for power comparisons is useful. Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index fe19ba3360a..0d7e2d324f1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3788,7 +3788,7 @@ static void valleyview_enable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_ring_buffer *ring; - u32 gtfifodbg, val; + u32 gtfifodbg, val, rc6_mode = 0; int i; WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); @@ -3828,8 +3828,9 @@ static void valleyview_enable_rps(struct drm_device *dev) /* allows RC6 residency counter to work */ I915_WRITE(0x138104, _MASKED_BIT_ENABLE(0x3)); - I915_WRITE(GEN6_RC_CONTROL, - GEN7_RC_CTL_TO_MODE); + if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) + rc6_mode = GEN7_RC_CTL_TO_MODE; + I915_WRITE(GEN6_RC_CONTROL, rc6_mode); val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); switch ((val >> 6) & 3) { -- cgit v1.2.3-70-g09d2 From 9cdb826c1452eeef1dfb5ebe64c27e7fa8616c49 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 16 Sep 2013 17:38:27 +0300 Subject: drm/i915: Change i915_request power well handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorganize the internal i915_request power well handling to use the reference count just like everyone else. This way all we need to do is check the reference count and we know whether the power well needs to be enabled of disabled. v2: Split he intel_display_power_{get,put} change to another patch. Add intel_resume_power_well() to make sure we enable the power well on resume Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 43 +++++++++++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b85354f9440..f1f11d10e48 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -764,6 +764,7 @@ extern bool intel_display_power_enabled(struct drm_device *dev, enum intel_display_power_domain domain); extern void intel_init_power_well(struct drm_device *dev); extern void intel_set_power_well(struct drm_device *dev, bool enable); +extern void intel_resume_power_well(struct drm_device *dev); extern void intel_enable_gt_powersave(struct drm_device *dev); extern void intel_disable_gt_powersave(struct drm_device *dev); extern void ironlake_teardown_rc6(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0d7e2d324f1..609c936d1df 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5354,8 +5354,7 @@ void i915_request_power_well(void) return; spin_lock_irq(&hsw_pwr->lock); - if (!hsw_pwr->count++ && - !hsw_pwr->i915_request) + if (!hsw_pwr->count++) __intel_set_power_well(hsw_pwr->device, true); spin_unlock_irq(&hsw_pwr->lock); } @@ -5369,8 +5368,7 @@ void i915_release_power_well(void) spin_lock_irq(&hsw_pwr->lock); WARN_ON(!hsw_pwr->count); - if (!--hsw_pwr->count && - !hsw_pwr->i915_request) + if (!--hsw_pwr->count) __intel_set_power_well(hsw_pwr->device, false); spin_unlock_irq(&hsw_pwr->lock); } @@ -5406,15 +5404,41 @@ void intel_set_power_well(struct drm_device *dev, bool enable) return; spin_lock_irq(&power_well->lock); + + /* + * This function will only ever contribute one + * to the power well reference count. i915_request + * is what tracks whether we have or have not + * added the one to the reference count. + */ + if (power_well->i915_request == enable) + goto out; + power_well->i915_request = enable; - /* only reject "disable" power well request */ - if (power_well->count && !enable) { - spin_unlock_irq(&power_well->lock); - return; + if (enable) { + if (!power_well->count++) + __intel_set_power_well(dev, true); + } else { + WARN_ON(!power_well->count); + if (!--power_well->count) + __intel_set_power_well(dev, false); } - __intel_set_power_well(dev, enable); + out: + spin_unlock_irq(&power_well->lock); +} + +void intel_resume_power_well(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_power_well *power_well = &dev_priv->power_well; + + if (!HAS_POWER_WELL(dev)) + return; + + spin_lock_irq(&power_well->lock); + __intel_set_power_well(dev, power_well->count > 0); spin_unlock_irq(&power_well->lock); } @@ -5433,6 +5457,7 @@ void intel_init_power_well(struct drm_device *dev) /* For now, we need the power well to be always enabled. */ intel_set_power_well(dev, true); + intel_resume_power_well(dev); /* We're taking over the BIOS, so clear any requests made by it since * the driver is in charge now. */ -- cgit v1.2.3-70-g09d2 From 6765625e0b677a86dbd533f045ab4e52e2761d79 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 16 Sep 2013 17:38:28 +0300 Subject: drm/i915: Add intel_display_power_{get, put} to request power for specific domains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add APIs to get/put power well references for specific purposes. v2: Split the i915_request change to another patch Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 4 +++ drivers/gpu/drm/i915/intel_pm.c | 63 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f1f11d10e48..1f052678035 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -762,6 +762,10 @@ extern void i915_remove_power_well(struct drm_device *dev); extern bool intel_display_power_enabled(struct drm_device *dev, enum intel_display_power_domain domain); +extern void intel_display_power_get(struct drm_device *dev, + enum intel_display_power_domain domain); +extern void intel_display_power_put(struct drm_device *dev, + enum intel_display_power_domain domain); extern void intel_init_power_well(struct drm_device *dev); extern void intel_set_power_well(struct drm_device *dev, bool enable); extern void intel_resume_power_well(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 609c936d1df..a0e198c8e14 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5345,6 +5345,69 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) } } +void intel_display_power_get(struct drm_device *dev, + enum intel_display_power_domain domain) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_power_well *power_well = &dev_priv->power_well; + + if (!HAS_POWER_WELL(dev)) + return; + + switch (domain) { + case POWER_DOMAIN_PIPE_A: + case POWER_DOMAIN_TRANSCODER_EDP: + return; + case POWER_DOMAIN_PIPE_B: + case POWER_DOMAIN_PIPE_C: + case POWER_DOMAIN_PIPE_A_PANEL_FITTER: + case POWER_DOMAIN_PIPE_B_PANEL_FITTER: + case POWER_DOMAIN_PIPE_C_PANEL_FITTER: + case POWER_DOMAIN_TRANSCODER_A: + case POWER_DOMAIN_TRANSCODER_B: + case POWER_DOMAIN_TRANSCODER_C: + spin_lock_irq(&power_well->lock); + if (!power_well->count++) + __intel_set_power_well(power_well->device, true); + spin_unlock_irq(&power_well->lock); + return; + default: + BUG(); + } +} + +void intel_display_power_put(struct drm_device *dev, + enum intel_display_power_domain domain) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_power_well *power_well = &dev_priv->power_well; + + if (!HAS_POWER_WELL(dev)) + return; + + switch (domain) { + case POWER_DOMAIN_PIPE_A: + case POWER_DOMAIN_TRANSCODER_EDP: + return; + case POWER_DOMAIN_PIPE_B: + case POWER_DOMAIN_PIPE_C: + case POWER_DOMAIN_PIPE_A_PANEL_FITTER: + case POWER_DOMAIN_PIPE_B_PANEL_FITTER: + case POWER_DOMAIN_PIPE_C_PANEL_FITTER: + case POWER_DOMAIN_TRANSCODER_A: + case POWER_DOMAIN_TRANSCODER_B: + case POWER_DOMAIN_TRANSCODER_C: + spin_lock_irq(&power_well->lock); + WARN_ON(!power_well->count); + if (!--power_well->count) + __intel_set_power_well(power_well->device, false); + spin_unlock_irq(&power_well->lock); + return; + default: + BUG(); + } +} + static struct i915_power_well *hsw_pwr; /* Display audio driver power well request */ -- cgit v1.2.3-70-g09d2 From 2d66aef508fc47aa75ed196bc4638636e28d1b42 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 16 Sep 2013 17:38:29 +0300 Subject: drm/i915: Refactor power well refcount inc/dec operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We increase/decrease the power well refcount in several places now, and all of those places need to do the same thing, so pull that code into a few small helper functions. v2: Rename the funcs to __intel_power_well_{get,put} Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a0e198c8e14..5e810bb21d8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5345,6 +5345,19 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) } } +static void __intel_power_well_get(struct i915_power_well *power_well) +{ + if (!power_well->count++) + __intel_set_power_well(power_well->device, true); +} + +static void __intel_power_well_put(struct i915_power_well *power_well) +{ + WARN_ON(!power_well->count); + if (!--power_well->count) + __intel_set_power_well(power_well->device, false); +} + void intel_display_power_get(struct drm_device *dev, enum intel_display_power_domain domain) { @@ -5367,8 +5380,7 @@ void intel_display_power_get(struct drm_device *dev, case POWER_DOMAIN_TRANSCODER_B: case POWER_DOMAIN_TRANSCODER_C: spin_lock_irq(&power_well->lock); - if (!power_well->count++) - __intel_set_power_well(power_well->device, true); + __intel_power_well_get(power_well); spin_unlock_irq(&power_well->lock); return; default: @@ -5398,9 +5410,7 @@ void intel_display_power_put(struct drm_device *dev, case POWER_DOMAIN_TRANSCODER_B: case POWER_DOMAIN_TRANSCODER_C: spin_lock_irq(&power_well->lock); - WARN_ON(!power_well->count); - if (!--power_well->count) - __intel_set_power_well(power_well->device, false); + __intel_power_well_put(power_well); spin_unlock_irq(&power_well->lock); return; default: @@ -5417,8 +5427,7 @@ void i915_request_power_well(void) return; spin_lock_irq(&hsw_pwr->lock); - if (!hsw_pwr->count++) - __intel_set_power_well(hsw_pwr->device, true); + __intel_power_well_get(hsw_pwr); spin_unlock_irq(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_request_power_well); @@ -5430,9 +5439,7 @@ void i915_release_power_well(void) return; spin_lock_irq(&hsw_pwr->lock); - WARN_ON(!hsw_pwr->count); - if (!--hsw_pwr->count) - __intel_set_power_well(hsw_pwr->device, false); + __intel_power_well_put(hsw_pwr); spin_unlock_irq(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_release_power_well); @@ -5479,14 +5486,10 @@ void intel_set_power_well(struct drm_device *dev, bool enable) power_well->i915_request = enable; - if (enable) { - if (!power_well->count++) - __intel_set_power_well(dev, true); - } else { - WARN_ON(!power_well->count); - if (!--power_well->count) - __intel_set_power_well(dev, false); - } + if (enable) + __intel_power_well_get(power_well); + else + __intel_power_well_put(power_well); out: spin_unlock_irq(&power_well->lock); -- cgit v1.2.3-70-g09d2 From cdf8dd7f888bb8b48adf2ae3babc5aad4b1a7a1e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 16 Sep 2013 17:38:30 +0300 Subject: drm/i915: Add POWER_DOMAIN_VGA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VGA registers/memory live inside the the display power well. Add a power domain for VGA. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 09a5c829168..8c52cbdb76f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -99,6 +99,7 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_B, POWER_DOMAIN_TRANSCODER_C, POWER_DOMAIN_TRANSCODER_EDP = POWER_DOMAIN_TRANSCODER_A + 0xF, + POWER_DOMAIN_VGA, }; #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5e810bb21d8..6789dcdb9b1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5283,6 +5283,7 @@ bool intel_display_power_enabled(struct drm_device *dev, case POWER_DOMAIN_PIPE_A: case POWER_DOMAIN_TRANSCODER_EDP: return true; + case POWER_DOMAIN_VGA: case POWER_DOMAIN_PIPE_B: case POWER_DOMAIN_PIPE_C: case POWER_DOMAIN_PIPE_A_PANEL_FITTER: @@ -5371,6 +5372,7 @@ void intel_display_power_get(struct drm_device *dev, case POWER_DOMAIN_PIPE_A: case POWER_DOMAIN_TRANSCODER_EDP: return; + case POWER_DOMAIN_VGA: case POWER_DOMAIN_PIPE_B: case POWER_DOMAIN_PIPE_C: case POWER_DOMAIN_PIPE_A_PANEL_FITTER: @@ -5401,6 +5403,7 @@ void intel_display_power_put(struct drm_device *dev, case POWER_DOMAIN_PIPE_A: case POWER_DOMAIN_TRANSCODER_EDP: return; + case POWER_DOMAIN_VGA: case POWER_DOMAIN_PIPE_B: case POWER_DOMAIN_PIPE_C: case POWER_DOMAIN_PIPE_A_PANEL_FITTER: -- cgit v1.2.3-70-g09d2 From b14c5679dd2c87b5bd14c49c5bdd1962be2ab209 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 19 Sep 2013 12:18:32 +0200 Subject: drm/i915: use pointer = k[cmz...]alloc(sizeof(*pointer), ...) pattern Done while reviewing all our allocations for fubar. Also a few errant cases of lacking () for the sizeof operator - just a bit of OCD. I've left out all the conversions that also should use kcalloc from this patch (it's only 2). Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_dma.c | 6 +++--- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_ddi.c | 6 +++--- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- drivers/gpu/drm/i915/intel_dvo.c | 4 ++-- drivers/gpu/drm/i915/intel_fb.c | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 4 ++-- drivers/gpu/drm/i915/intel_lvds.c | 4 ++-- drivers/gpu/drm/i915/intel_overlay.c | 4 ++-- drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/i915/intel_sdvo.c | 10 +++++----- drivers/gpu/drm/i915/intel_sprite.c | 2 +- drivers/gpu/drm/i915/intel_tv.c | 4 ++-- 16 files changed, 30 insertions(+), 30 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 80bed69fe5b..09c93d7989f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2156,7 +2156,7 @@ drm_add_fake_info_node(struct drm_minor *minor, { struct drm_info_node *node; - node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL); + node = kmalloc(sizeof(*node), GFP_KERNEL); if (node == NULL) { debugfs_remove(ent); return -ENOMEM; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 512645fdaff..aa69c735298 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -641,7 +641,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, if (batch->num_cliprects) { cliprects = kcalloc(batch->num_cliprects, - sizeof(struct drm_clip_rect), + sizeof(*cliprects), GFP_KERNEL); if (cliprects == NULL) return -ENOMEM; @@ -703,7 +703,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, if (cmdbuf->num_cliprects) { cliprects = kcalloc(cmdbuf->num_cliprects, - sizeof(struct drm_clip_rect), GFP_KERNEL); + sizeof(*cliprects), GFP_KERNEL); if (cliprects == NULL) { ret = -ENOMEM; goto fail_batch_free; @@ -1480,7 +1480,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev->types[8] = _DRM_STAT_SECONDARY; dev->types[9] = _DRM_STAT_DMA; - dev_priv = kzalloc(sizeof(drm_i915_private_t), GFP_KERNEL); + dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); if (dev_priv == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 36c4ad9c752..96f65a15ffc 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4638,7 +4638,7 @@ static int i915_gem_init_phys_object(struct drm_device *dev, if (dev_priv->mm.phys_objs[id - 1] || !size) return 0; - phys_obj = kzalloc(sizeof(struct drm_i915_gem_phys_object), GFP_KERNEL); + phys_obj = kzalloc(sizeof(*phys_obj), GFP_KERNEL); if (!phys_obj) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 6f101d5620e..f9a5f3d1f0c 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -764,7 +764,7 @@ void intel_crt_init(struct drm_device *dev) if (!crt) return; - intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(crt); return; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 04f68804834..351e21a0be0 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1337,11 +1337,11 @@ void intel_ddi_init(struct drm_device *dev, enum port port) struct intel_connector *hdmi_connector = NULL; struct intel_connector *dp_connector = NULL; - intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); + intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); if (!intel_dig_port) return; - dp_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + dp_connector = kzalloc(sizeof(*dp_connector), GFP_KERNEL); if (!dp_connector) { kfree(intel_dig_port); return; @@ -1381,7 +1381,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) } if (intel_encoder->type != INTEL_OUTPUT_EDP) { - hdmi_connector = kzalloc(sizeof(struct intel_connector), + hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL); if (!hdmi_connector) { return; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index bef786461a3..96a0924ed75 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8097,7 +8097,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, fb->pitches[0] != crtc->fb->pitches[0])) return -EINVAL; - work = kzalloc(sizeof *work, GFP_KERNEL); + work = kzalloc(sizeof(*work), GFP_KERNEL); if (work == NULL) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 60d2006fe15..7e4052ea99c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3625,11 +3625,11 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port) struct drm_encoder *encoder; struct intel_connector *intel_connector; - intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); + intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); if (!intel_dig_port) return; - intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(intel_dig_port); return; diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index ff86c366218..6305433797a 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -448,11 +448,11 @@ void intel_dvo_init(struct drm_device *dev) int i; int encoder_type = DRM_MODE_ENCODER_NONE; - intel_dvo = kzalloc(sizeof(struct intel_dvo), GFP_KERNEL); + intel_dvo = kzalloc(sizeof(*intel_dvo), GFP_KERNEL); if (!intel_dvo) return; - intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(intel_dvo); return; diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index bc2100007b2..6aa66aaceae 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -216,7 +216,7 @@ int intel_fbdev_init(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; int ret; - ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); + ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL); if (!ifbdev) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 79582f91241..a6310ca444c 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1292,11 +1292,11 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) struct intel_encoder *intel_encoder; struct intel_connector *intel_connector; - intel_dig_port = kzalloc(sizeof(struct intel_digital_port), GFP_KERNEL); + intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL); if (!intel_dig_port) return; - intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(intel_dig_port); return; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 05e5485a630..639650c66e5 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -948,11 +948,11 @@ void intel_lvds_init(struct drm_device *dev) } } - lvds_encoder = kzalloc(sizeof(struct intel_lvds_encoder), GFP_KERNEL); + lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL); if (!lvds_encoder) return; - lvds_connector = kzalloc(sizeof(struct intel_lvds_connector), GFP_KERNEL); + lvds_connector = kzalloc(sizeof(*lvds_connector), GFP_KERNEL); if (!lvds_connector) { kfree(lvds_encoder); return; diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 8d6d0a1bf5b..a98a990fbab 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -1053,7 +1053,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data, return ret; } - params = kmalloc(sizeof(struct put_image_params), GFP_KERNEL); + params = kmalloc(sizeof(*params), GFP_KERNEL); if (!params) return -ENOMEM; @@ -1320,7 +1320,7 @@ void intel_setup_overlay(struct drm_device *dev) if (!HAS_OVERLAY(dev)) return; - overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL); + overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); if (!overlay) return; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4692f8cb772..d27eda66154 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -370,7 +370,7 @@ static void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval) intel_cancel_fbc_work(dev_priv); - work = kzalloc(sizeof *work, GFP_KERNEL); + work = kzalloc(sizeof(*work), GFP_KERNEL); if (work == NULL) { DRM_ERROR("Failed to allocate FBC work structure\n"); dev_priv->display.enable_fbc(crtc, interval); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 91aea9e1ab6..d8040e8a68b 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2397,7 +2397,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); if (!intel_sdvo_connector) return false; @@ -2445,7 +2445,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); if (!intel_sdvo_connector) return false; @@ -2482,7 +2482,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); if (!intel_sdvo_connector) return false; @@ -2513,7 +2513,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - intel_sdvo_connector = kzalloc(sizeof(struct intel_sdvo_connector), GFP_KERNEL); + intel_sdvo_connector = kzalloc(sizeof(*intel_sdvo_connector), GFP_KERNEL); if (!intel_sdvo_connector) return false; @@ -2879,7 +2879,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) struct intel_encoder *intel_encoder; struct intel_sdvo *intel_sdvo; int i; - intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); + intel_sdvo = kzalloc(sizeof(*intel_sdvo), GFP_KERNEL); if (!intel_sdvo) return false; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 231b289e8e5..cae10bc746d 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1034,7 +1034,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) if (INTEL_INFO(dev)->gen < 5) return -ENODEV; - intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL); + intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); if (!intel_plane) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index dd6f84bf6c2..e6e93ce34f7 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1590,12 +1590,12 @@ intel_tv_init(struct drm_device *dev) (tv_dac_off & TVDAC_STATE_CHG_EN) != 0) return; - intel_tv = kzalloc(sizeof(struct intel_tv), GFP_KERNEL); + intel_tv = kzalloc(sizeof(*intel_tv), GFP_KERNEL); if (!intel_tv) { return; } - intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); + intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); if (!intel_connector) { kfree(intel_tv); return; -- cgit v1.2.3-70-g09d2 From 241bfc389111ce4c997430e6cd1532a08b16dc6b Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Wed, 25 Sep 2013 16:45:37 +0100 Subject: drm/i915: Use crtc_clock with the adjusted mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct drm_mode_display now has a separate crtc_ version of the clock to be used when we're talking about the timings given to the harwadre (was far as the mode is concerned). This commit is really the result of a git grep adjusted_mode.*clock and replacing those by adjusted_mode.crtc_clock. No functional change. v2: Rebased on drm-intel-queued-next Reviewed-by: Ville Syrjälä Signed-off-by: Damien Lespiau Acked-by: Dave Airlie Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 34 +++++++++++++++++----------------- drivers/gpu/drm/i915/intel_dp.c | 11 +++++++---- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_dvo.c | 2 +- drivers/gpu/drm/i915/intel_hdmi.c | 6 +++--- drivers/gpu/drm/i915/intel_lvds.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 36 +++++++++++++++++++++++------------- drivers/gpu/drm/i915/intel_sdvo.c | 2 +- drivers/gpu/drm/i915/intel_tv.c | 2 +- 10 files changed, 56 insertions(+), 43 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 019c4cea7bb..0263629332d 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -117,7 +117,7 @@ static void intel_crt_get_config(struct intel_encoder *encoder, if (HAS_PCH_SPLIT(dev)) ironlake_check_encoder_dotclock(pipe_config, dotclock); - pipe_config->adjusted_mode.clock = dotclock; + pipe_config->adjusted_mode.crtc_clock = dotclock; } static void hsw_crt_get_config(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 282d83a2a73..3085da1487c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -739,14 +739,14 @@ bool intel_crtc_active(struct drm_crtc *crtc) /* Be paranoid as we can arrive here with only partial * state retrieved from the hardware during setup. * - * We can ditch the adjusted_mode.clock check as soon + * We can ditch the adjusted_mode.crtc_clock check as soon * as Haswell has gained clock readout/fastboot support. * * We can ditch the crtc->fb check as soon as we can * properly reconstruct framebuffers. */ return intel_crtc->active && crtc->fb && - intel_crtc->config.adjusted_mode.clock; + intel_crtc->config.adjusted_mode.crtc_clock; } enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, @@ -2913,7 +2913,7 @@ static void lpt_program_iclkip(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - int clock = to_intel_crtc(crtc)->config.adjusted_mode.clock; + int clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; u32 divsel, phaseinc, auxdiv, phasedir = 0; u32 temp; @@ -2937,8 +2937,8 @@ static void lpt_program_iclkip(struct drm_crtc *crtc) phaseinc = 0x20; } else { /* The iCLK virtual clock root frequency is in MHz, - * but the adjusted_mode->clock in in KHz. To get the divisors, - * it is necessary to divide one by another, so we + * but the adjusted_mode->crtc_clock in in KHz. To get the + * divisors, it is necessary to divide one by another, so we * convert the virtual clock precision to KHz here for higher * precision. */ @@ -4148,7 +4148,7 @@ retry: */ link_bw = intel_fdi_link_freq(dev) * MHz(100)/KHz(1)/10; - fdi_dotclock = adjusted_mode->clock; + fdi_dotclock = adjusted_mode->crtc_clock; lane = ironlake_get_lanes_required(fdi_dotclock, link_bw, pipe_config->pipe_bpp); @@ -4204,12 +4204,12 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, * otherwise pipe A only. */ if ((crtc->pipe == PIPE_A || IS_I915G(dev)) && - adjusted_mode->clock > clock_limit * 9 / 10) { + adjusted_mode->crtc_clock > clock_limit * 9 / 10) { clock_limit *= 2; pipe_config->double_wide = true; } - if (adjusted_mode->clock > clock_limit * 9 / 10) + if (adjusted_mode->crtc_clock > clock_limit * 9 / 10) return -EINVAL; } @@ -4869,7 +4869,7 @@ static void intel_crtc_mode_from_pipe_config(struct intel_crtc *intel_crtc, crtc->mode.flags = pipe_config->adjusted_mode.flags; - crtc->mode.clock = pipe_config->adjusted_mode.clock; + crtc->mode.clock = pipe_config->adjusted_mode.crtc_clock; crtc->mode.flags |= pipe_config->adjusted_mode.flags; } @@ -7473,7 +7473,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, /* * This value includes pixel_multiplier. We will use - * port_clock to compute adjusted_mode.clock in the + * port_clock to compute adjusted_mode.crtc_clock in the * encoder's get_config() function. */ pipe_config->port_clock = clock.dot; @@ -7508,11 +7508,11 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc, /* * This value does not include pixel_multiplier. - * We will check that port_clock and adjusted_mode.clock + * We will check that port_clock and adjusted_mode.crtc_clock * agree once we know their relationship in the encoder's * get_config() function. */ - pipe_config->adjusted_mode.clock = + pipe_config->adjusted_mode.crtc_clock = intel_dotclock_calculate(intel_fdi_link_freq(dev) * 10000, &pipe_config->fdi_m_n); } @@ -8489,8 +8489,8 @@ encoder_retry: /* Set default port clock if not overwritten by the encoder. Needs to be * done afterwards in case the encoder adjusts the mode. */ if (!pipe_config->port_clock) - pipe_config->port_clock = pipe_config->adjusted_mode.clock * - pipe_config->pixel_multiplier; + pipe_config->port_clock = pipe_config->adjusted_mode.crtc_clock + * pipe_config->pixel_multiplier; ret = intel_crtc_compute_config(to_intel_crtc(crtc), pipe_config); if (ret < 0) { @@ -8820,7 +8820,7 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_I(pipe_bpp); if (!IS_HASWELL(dev)) { - PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.clock); + PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock); PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); } @@ -9042,9 +9042,9 @@ void ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config * FDI already provided one idea for the dotclock. * Yell if the encoder disagrees. */ - WARN(!intel_fuzzy_clock_check(pipe_config->adjusted_mode.clock, dotclock), + WARN(!intel_fuzzy_clock_check(pipe_config->adjusted_mode.crtc_clock, dotclock), "FDI dotclock and encoder dotclock mismatch, fdi: %i, encoder: %i\n", - pipe_config->adjusted_mode.clock, dotclock); + pipe_config->adjusted_mode.crtc_clock, dotclock); } static int __intel_set_mode(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a5e4e612d8f..95a31598fed 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -811,7 +811,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, DRM_DEBUG_KMS("DP link computation with max lane count %i " "max bw %02x pixel clock %iKHz\n", - max_lane_count, bws[max_clock], adjusted_mode->clock); + max_lane_count, bws[max_clock], + adjusted_mode->crtc_clock); /* Walk through all bpp values. Luckily they're all nicely spaced with 2 * bpc in between. */ @@ -823,7 +824,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, } for (; bpp >= 6*3; bpp -= 2*3) { - mode_rate = intel_dp_link_required(adjusted_mode->clock, bpp); + mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock, + bpp); for (clock = 0; clock <= max_clock; clock++) { for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { @@ -868,7 +870,8 @@ found: mode_rate, link_avail); intel_link_compute_m_n(bpp, lane_count, - adjusted_mode->clock, pipe_config->port_clock, + adjusted_mode->crtc_clock, + pipe_config->port_clock, &pipe_config->dp_m_n); intel_dp_set_clock(encoder, pipe_config, intel_dp->link_bw); @@ -1483,7 +1486,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder, if (HAS_PCH_SPLIT(dev_priv->dev) && port != PORT_A) ironlake_check_encoder_dotclock(pipe_config, dotclock); - pipe_config->adjusted_mode.clock = dotclock; + pipe_config->adjusted_mode.crtc_clock = dotclock; } static bool is_edp_psr(struct intel_dp *intel_dp) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8c3cb3e3052..a17a86ac4e4 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -217,7 +217,7 @@ struct intel_crtc_config { * preferred input timings. */ struct drm_display_mode requested_mode; /* Actual pipe timings ie. what we program into the pipe timing - * registers. adjusted_mode.clock is the pipe pixel clock. */ + * registers. adjusted_mode.crtc_clock is the pipe pixel clock. */ struct drm_display_mode adjusted_mode; /* Pipe source size (ie. panel fitter input size) diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 6305433797a..91287d1d305 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -154,7 +154,7 @@ static void intel_dvo_get_config(struct intel_encoder *encoder, pipe_config->adjusted_mode.flags |= flags; - pipe_config->adjusted_mode.clock = pipe_config->port_clock; + pipe_config->adjusted_mode.crtc_clock = pipe_config->port_clock; } static void intel_disable_dvo(struct intel_encoder *encoder) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index a6310ca444c..1a57758e5bf 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -737,7 +737,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, if (HAS_PCH_SPLIT(dev_priv->dev)) ironlake_check_encoder_dotclock(pipe_config, dotclock); - pipe_config->adjusted_mode.clock = dotclock; + pipe_config->adjusted_mode.crtc_clock = dotclock; } static void intel_enable_hdmi(struct intel_encoder *encoder) @@ -873,7 +873,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); struct drm_device *dev = encoder->base.dev; struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; - int clock_12bpc = pipe_config->adjusted_mode.clock * 3 / 2; + int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2; int portclock_limit = hdmi_portclock_limit(intel_hdmi); int desired_bpp; @@ -915,7 +915,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, pipe_config->pipe_bpp = desired_bpp; } - if (adjusted_mode->clock > portclock_limit) { + if (adjusted_mode->crtc_clock > portclock_limit) { DRM_DEBUG_KMS("too high HDMI clock, rejecting mode\n"); return false; } diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 67a4a8fd5f8..fb3f8efcc6e 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -123,7 +123,7 @@ static void intel_lvds_get_config(struct intel_encoder *encoder, if (HAS_PCH_SPLIT(dev_priv->dev)) ironlake_check_encoder_dotclock(pipe_config, dotclock); - pipe_config->adjusted_mode.clock = dotclock; + pipe_config->adjusted_mode.crtc_clock = dotclock; } /* The LVDS pin pair needs to be on before the DPLLs are enabled. diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d27eda66154..2ac1c2fd58b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1100,8 +1100,12 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc) crtc = single_enabled_crtc(dev); if (crtc) { - int clock = to_intel_crtc(crtc)->config.adjusted_mode.clock; + const struct drm_display_mode *adjusted_mode; int pixel_size = crtc->fb->bits_per_pixel / 8; + int clock; + + adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; + clock = adjusted_mode->crtc_clock; /* Display SR */ wm = intel_calculate_wm(clock, &pineview_display_wm, @@ -1174,7 +1178,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, } adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; - clock = adjusted_mode->clock; + clock = adjusted_mode->crtc_clock; htotal = adjusted_mode->htotal; hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; pixel_size = crtc->fb->bits_per_pixel / 8; @@ -1261,7 +1265,7 @@ static bool g4x_compute_srwm(struct drm_device *dev, crtc = intel_get_crtc_for_plane(dev, plane); adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; - clock = adjusted_mode->clock; + clock = adjusted_mode->crtc_clock; htotal = adjusted_mode->htotal; hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; pixel_size = crtc->fb->bits_per_pixel / 8; @@ -1302,7 +1306,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, if (!intel_crtc_active(crtc)) return false; - clock = to_intel_crtc(crtc)->config.adjusted_mode.clock; + clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; pixel_size = crtc->fb->bits_per_pixel / 8; /* BPP */ entries = (clock / 1000) * pixel_size; @@ -1492,7 +1496,7 @@ static void i965_update_wm(struct drm_crtc *unused_crtc) static const int sr_latency_ns = 12000; const struct drm_display_mode *adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; - int clock = adjusted_mode->clock; + int clock = adjusted_mode->crtc_clock; int htotal = adjusted_mode->htotal; int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; int pixel_size = crtc->fb->bits_per_pixel / 8; @@ -1567,11 +1571,13 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) fifo_size = dev_priv->display.get_fifo_size(dev, 0); crtc = intel_get_crtc_for_plane(dev, 0); if (intel_crtc_active(crtc)) { + const struct drm_display_mode *adjusted_mode; int cpp = crtc->fb->bits_per_pixel / 8; if (IS_GEN2(dev)) cpp = 4; - planea_wm = intel_calculate_wm(to_intel_crtc(crtc)->config.adjusted_mode.clock, + adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; + planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, wm_info, fifo_size, cpp, latency_ns); enabled = crtc; @@ -1581,11 +1587,13 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) fifo_size = dev_priv->display.get_fifo_size(dev, 1); crtc = intel_get_crtc_for_plane(dev, 1); if (intel_crtc_active(crtc)) { + const struct drm_display_mode *adjusted_mode; int cpp = crtc->fb->bits_per_pixel / 8; if (IS_GEN2(dev)) cpp = 4; - planeb_wm = intel_calculate_wm(to_intel_crtc(crtc)->config.adjusted_mode.clock, + adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; + planeb_wm = intel_calculate_wm(adjusted_mode->crtc_clock, wm_info, fifo_size, cpp, latency_ns); if (enabled == NULL) @@ -1614,7 +1622,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) static const int sr_latency_ns = 6000; const struct drm_display_mode *adjusted_mode = &to_intel_crtc(enabled)->config.adjusted_mode; - int clock = adjusted_mode->clock; + int clock = adjusted_mode->crtc_clock; int htotal = adjusted_mode->htotal; int hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; int pixel_size = enabled->fb->bits_per_pixel / 8; @@ -1670,6 +1678,7 @@ static void i830_update_wm(struct drm_crtc *unused_crtc) struct drm_device *dev = unused_crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc; + const struct drm_display_mode *adjusted_mode; uint32_t fwater_lo; int planea_wm; @@ -1677,7 +1686,8 @@ static void i830_update_wm(struct drm_crtc *unused_crtc) if (crtc == NULL) return; - planea_wm = intel_calculate_wm(to_intel_crtc(crtc)->config.adjusted_mode.clock, + adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; + planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock, &i830_wm_info, dev_priv->display.get_fifo_size(dev, 0), 4, latency_ns); @@ -1764,7 +1774,7 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane, crtc = intel_get_crtc_for_plane(dev, plane); adjusted_mode = &to_intel_crtc(crtc)->config.adjusted_mode; - clock = adjusted_mode->clock; + clock = adjusted_mode->crtc_clock; htotal = adjusted_mode->htotal; hdisplay = to_intel_crtc(crtc)->config.pipe_src_w; pixel_size = crtc->fb->bits_per_pixel / 8; @@ -2112,7 +2122,7 @@ static uint32_t ilk_pipe_pixel_rate(struct drm_device *dev, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); uint32_t pixel_rate; - pixel_rate = intel_crtc->config.adjusted_mode.clock; + pixel_rate = intel_crtc->config.adjusted_mode.crtc_clock; /* We only use IF-ID interlacing. If we ever use PF-ID we'll need to * adjust the pixel_rate here. */ @@ -2913,7 +2923,7 @@ sandybridge_compute_sprite_wm(struct drm_device *dev, int plane, return false; } - clock = to_intel_crtc(crtc)->config.adjusted_mode.clock; + clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; /* Use the small buffer method to calculate the sprite watermark */ entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; @@ -2948,7 +2958,7 @@ sandybridge_compute_sprite_srwm(struct drm_device *dev, int plane, } crtc = intel_get_crtc_for_plane(dev, plane); - clock = to_intel_crtc(crtc)->config.adjusted_mode.clock; + clock = to_intel_crtc(crtc)->config.adjusted_mode.crtc_clock; if (!clock) { *sprite_wm = 0; return false; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 606e0327920..5e59d64cfd9 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1369,7 +1369,7 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, if (HAS_PCH_SPLIT(dev)) ironlake_check_encoder_dotclock(pipe_config, dotclock); - pipe_config->adjusted_mode.clock = dotclock; + pipe_config->adjusted_mode.crtc_clock = dotclock; /* Cross check the port pixel multiplier with the sdvo encoder state. */ if (intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_CLOCK_RATE_MULT, diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 11c15fbf9e5..75925a1ab35 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -912,7 +912,7 @@ intel_tv_compute_config(struct intel_encoder *encoder, if (!tv_mode) return false; - pipe_config->adjusted_mode.clock = tv_mode->clock; + pipe_config->adjusted_mode.crtc_clock = tv_mode->clock; DRM_DEBUG_KMS("forcing bpc to 8 for TV\n"); pipe_config->pipe_bpp = 8*3; -- cgit v1.2.3-70-g09d2 From 49798eb2fe7240900d0a22a4e8d2b8e2f2ea6684 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 26 Sep 2013 17:55:57 -0700 Subject: drm/i915/vlv: use lower precision RC6 counter And add some reg defines while we're at it. Since the units of the RC6 residency counter are actually in CZ clocks, we want to just use the high bits or we'll overflow too frequently. Signed-off-by: Jesse Barnes Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 4 ++++ drivers/gpu/drm/i915/intel_pm.c | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 33bb4750516..c15cc749ca2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4729,6 +4729,10 @@ GEN6_PM_RP_DOWN_TIMEOUT) #define GEN6_GT_GFX_RC6_LOCKED 0x138104 +#define VLV_COUNTER_CONTROL 0x138104 +#define VLV_COUNT_RANGE_HIGH (1<<15) +#define VLV_MEDIA_RC6_COUNT_EN (1<<1) +#define VLV_RENDER_RC6_COUNT_EN (1<<0) #define GEN6_GT_GFX_RC6 0x138108 #define GEN6_GT_GFX_RC6p 0x13810C #define GEN6_GT_GFX_RC6pp 0x138110 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2ac1c2fd58b..102fc498a12 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3837,7 +3837,10 @@ static void valleyview_enable_rps(struct drm_device *dev) I915_WRITE(GEN6_RC6_THRESHOLD, 0xc350); /* allows RC6 residency counter to work */ - I915_WRITE(0x138104, _MASKED_BIT_ENABLE(0x3)); + I915_WRITE(VLV_COUNTER_CONTROL, + _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH | + VLV_MEDIA_RC6_COUNT_EN | + VLV_RENDER_RC6_COUNT_EN)); if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) rc6_mode = GEN7_RC_CTL_TO_MODE; I915_WRITE(GEN6_RC_CONTROL, rc6_mode); -- cgit v1.2.3-70-g09d2 From f7d85c1ed1562aaab3ce10714cdd9e68013de7ae Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 27 Sep 2013 10:40:54 -0700 Subject: drm/i915/vlv: reduce GT FIFO error info to a debug message It indicates a probable BIOS bug, but it appears to be harmless, and there's nothing the user can do about it anyway, so reduce to a debug msg. I've filed a bug with the BIOS folks about it anyway, so hopefully they'll fix whatever GT SB read they were doing when the GT was off. References: https://bugs.freedesktop.org/show_bug.cgi?id=69396 Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 102fc498a12..10054b58ee9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3804,7 +3804,8 @@ static void valleyview_enable_rps(struct drm_device *dev) WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); if ((gtfifodbg = I915_READ(GTFIFODBG))) { - DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg); + DRM_DEBUG_DRIVER("GT fifo had a previous error %x\n", + gtfifodbg); I915_WRITE(GTFIFODBG, gtfifodbg); } -- cgit v1.2.3-70-g09d2 From 5134099089b539e18afb9d06313508317fb35504 Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Sat, 28 Sep 2013 16:46:56 +0100 Subject: drm/i915: Make intel_resume_power_well() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Damien Lespiau Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 1 - drivers/gpu/drm/i915/intel_pm.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a17a86ac4e4..e6db0c67e0b 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -798,7 +798,6 @@ void intel_display_power_put(struct drm_device *dev, enum intel_display_power_domain domain); void intel_init_power_well(struct drm_device *dev); void intel_set_power_well(struct drm_device *dev, bool enable); -void intel_resume_power_well(struct drm_device *dev); void intel_enable_gt_powersave(struct drm_device *dev); void intel_disable_gt_powersave(struct drm_device *dev); void ironlake_teardown_rc6(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 10054b58ee9..698257cf638 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5512,7 +5512,7 @@ void intel_set_power_well(struct drm_device *dev, bool enable) spin_unlock_irq(&power_well->lock); } -void intel_resume_power_well(struct drm_device *dev) +static void intel_resume_power_well(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_well *power_well = &dev_priv->power_well; -- cgit v1.2.3-70-g09d2 From f6aca45c060d43db083a5ae34ac6ad3bbefe81da Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 2 Oct 2013 09:25:02 -0700 Subject: drm/i915: Clean up the ring scaling calculations This patch attempts to clean up the ring/IA scaling programming in the following ways. 1. Fix the comment about the DDR frequency. The math is 266MHz, not 133MHz. Formula was right, docs are wrong. 2. Mask the DCLK register since I don't know how it is defined on future platforms. 3. use mult_frac instead of magic math. This helps for future platform enabling. v2: Actually use the right patch. The v1 was a mix of things, none of which was right. Note that due to rounding, we actually get different values (slightly higher) for the effective ring frequency. v3: Use 1.25 instead of 1.33 as the original code did. (Jesse) CC: Jesse Barnes CC: Chris Wilson Signed-off-by: Ben Widawsky Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 698257cf638..9753bd9591e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3663,9 +3663,9 @@ void gen6_update_ring_freq(struct drm_device *dev) /* Convert from kHz to MHz */ max_ia_freq /= 1000; - min_ring_freq = I915_READ(MCHBAR_MIRROR_BASE_SNB + DCLK); - /* convert DDR frequency from units of 133.3MHz to bandwidth */ - min_ring_freq = (2 * 4 * min_ring_freq + 2) / 3; + min_ring_freq = I915_READ(MCHBAR_MIRROR_BASE_SNB + DCLK) & 0xf; + /* convert DDR frequency from units of 266.6MHz to bandwidth */ + min_ring_freq = mult_frac(min_ring_freq, 8, 3); /* * For each potential GPU frequency, load a ring frequency we'd like @@ -3678,7 +3678,7 @@ void gen6_update_ring_freq(struct drm_device *dev) unsigned int ia_freq = 0, ring_freq = 0; if (IS_HASWELL(dev)) { - ring_freq = (gpu_freq * 5 + 3) / 4; + ring_freq = mult_frac(gpu_freq, 5, 4); ring_freq = max(min_ring_freq, ring_freq); /* leave ia_freq as the default, chosen by cpufreq */ } else { -- cgit v1.2.3-70-g09d2 From b29c19b645287f7062e17d70fa4e9781a01a5d88 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 25 Sep 2013 17:34:56 +0100 Subject: drm/i915: Boost RPS frequency for CPU stalls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we encounter a situation where the CPU blocks waiting for results from the GPU, give the GPU a kick to boost its the frequency. This should work to reduce user interface stalls and to quickly promote mesa to high frequencies - but the cost is that our requested frequency stalls high (as we do not idle for long enough before rc6 to start reducing frequencies, nor are we aggressive at down clocking an underused GPU). However, this should be mitigated by rc6 itself powering off the GPU when idle, and that energy use is dependent upon the workload of the GPU in addition to its frequency (e.g. the math or sampler functions only consume power when used). Still, this is likely to adversely affect light workloads. In particular, this nearly eliminates the highly noticeable wake-up lag in animations from idle. For example, expose or workspace transitions. (However, given the situation where we fail to downclock, our requested frequency is almost always the maximum, except for Baytrail where we manually downclock upon idling. This often masks the latency of upclocking after being idle, so animations are typically smooth - at the cost of increased power consumption.) Stéphane raised the concern that this will punish good applications and reward bad applications - but due to the nature of how mesa performs its client throttling, I believe all mesa applications will be roughly equally affected. To address this concern, and to prevent applications like compositors from permanently boosting the RPS state, we ratelimit the frequency of the wait-boosts each client recieves. Unfortunately, this techinique is ineffective with Ironlake - which also has dynamic render power states and suffers just as dramatically. For Ironlake, the thermal/power headroom is shared with the CPU through Intelligent Power Sharing and the intel-ips module. This leaves us with no GPU boost frequencies available when coming out of idle, and due to hardware limitations we cannot change the arbitration between the CPU and GPU quickly enough to be effective. v2: Limit each client to receiving a single boost for each active period. Tested by QA to only marginally increase power, and to demonstrably increase throughput in games. No latency measurements yet. v3: Cater for front-buffer rendering with manual throttling. v4: Tidy up. v5: Sadly the compositor needs frequent boosts as it may never idle, but due to its picking mechanism (using ReadPixels) may require frequent waits. Those waits, along with the waits for the vrefresh swap, conspire to keep the GPU at low frequencies despite the interactive latency. To overcome this we ditch the one-boost-per-active-period and just ratelimit the number of wait-boosts each client can receive. Reported-and-tested-by: Paul Neumann Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=68716 Signed-off-by: Chris Wilson Cc: Kenneth Graunke Cc: Stéphane Marchesin Cc: Owen Taylor Cc: "Meng, Mengmeng" Cc: "Zhuang, Lena" Reviewed-by: Jesse Barnes [danvet: No extern for function prototypes in headers.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 16 ++--- drivers/gpu/drm/i915/i915_drv.h | 19 +++-- drivers/gpu/drm/i915/i915_gem.c | 135 ++++++++++++++++++++++++----------- drivers/gpu/drm/i915/i915_irq.c | 11 --- drivers/gpu/drm/i915/intel_display.c | 3 + drivers/gpu/drm/i915/intel_drv.h | 3 + drivers/gpu/drm/i915/intel_pm.c | 42 ++++++----- 7 files changed, 138 insertions(+), 91 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2b9725f7bf2..f221631cdc8 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1827,19 +1827,11 @@ int i915_driver_unload(struct drm_device *dev) int i915_driver_open(struct drm_device *dev, struct drm_file *file) { - struct drm_i915_file_private *file_priv; - - DRM_DEBUG_DRIVER("\n"); - file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); - if (!file_priv) - return -ENOMEM; - - file->driver_priv = file_priv; - - spin_lock_init(&file_priv->mm.lock); - INIT_LIST_HEAD(&file_priv->mm.request_list); + int ret; - idr_init(&file_priv->context_idr); + ret = i915_gem_open(dev, file); + if (ret) + return ret; return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 79bbcf925e4..d1c6b92edae 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -844,9 +844,6 @@ struct intel_gen6_power_mgmt { struct work_struct work; u32 pm_iir; - /* On vlv we need to manually drop to Vmin with a delayed work. */ - struct delayed_work vlv_work; - /* The below variables an all the rps hw state are protected by * dev->struct mutext. */ u8 cur_delay; @@ -964,6 +961,15 @@ struct i915_gem_mm { */ struct delayed_work retire_work; + /** + * When we detect an idle GPU, we want to turn on + * powersaving features. So once we see that there + * are no more requests outstanding and no more + * arrive within a small period of time, we fire + * off the idle_work. + */ + struct delayed_work idle_work; + /** * Are we in a non-interruptible section of code like * modesetting? @@ -1597,13 +1603,17 @@ struct drm_i915_gem_request { }; struct drm_i915_file_private { + struct drm_i915_private *dev_priv; + struct { spinlock_t lock; struct list_head request_list; + struct delayed_work idle_work; } mm; struct idr context_idr; struct i915_ctx_hang_stats hang_stats; + atomic_t rps_wait_boost; }; #define INTEL_INFO(dev) (to_i915(dev)->info) @@ -1953,7 +1963,7 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj) } } -void i915_gem_retire_requests(struct drm_device *dev); +bool i915_gem_retire_requests(struct drm_device *dev); void i915_gem_retire_requests_ring(struct intel_ring_buffer *ring); int __must_check i915_gem_check_wedge(struct i915_gpu_error *error, bool interruptible); @@ -2004,6 +2014,7 @@ int i915_gem_attach_phys_object(struct drm_device *dev, void i915_gem_detach_phys_object(struct drm_device *dev, struct drm_i915_gem_object *obj); void i915_gem_free_all_phys_object(struct drm_device *dev); +int i915_gem_open(struct drm_device *dev, struct drm_file *file); void i915_gem_release(struct drm_device *dev, struct drm_file *file); uint32_t diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 53e31513170..19ecfa8ad2e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -982,6 +982,14 @@ static bool missed_irq(struct drm_i915_private *dev_priv, return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings); } +static bool can_wait_boost(struct drm_i915_file_private *file_priv) +{ + if (file_priv == NULL) + return true; + + return !atomic_xchg(&file_priv->rps_wait_boost, true); +} + /** * __wait_seqno - wait until execution of seqno has finished * @ring: the ring expected to report seqno @@ -1002,7 +1010,9 @@ static bool missed_irq(struct drm_i915_private *dev_priv, */ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, unsigned reset_counter, - bool interruptible, struct timespec *timeout) + bool interruptible, + struct timespec *timeout, + struct drm_i915_file_private *file_priv) { drm_i915_private_t *dev_priv = ring->dev->dev_private; struct timespec before, now; @@ -1017,6 +1027,14 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, timeout_jiffies = timeout ? timespec_to_jiffies_timeout(timeout) : 1; + if (dev_priv->info->gen >= 6 && can_wait_boost(file_priv)) { + gen6_rps_boost(dev_priv); + if (file_priv) + mod_delayed_work(dev_priv->wq, + &file_priv->mm.idle_work, + msecs_to_jiffies(100)); + } + if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)) && WARN_ON(!ring->irq_get(ring))) return -ENODEV; @@ -1116,7 +1134,7 @@ i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno) return __wait_seqno(ring, seqno, atomic_read(&dev_priv->gpu_error.reset_counter), - interruptible, NULL); + interruptible, NULL, NULL); } static int @@ -1166,6 +1184,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, */ static __must_check int i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, + struct drm_file *file, bool readonly) { struct drm_device *dev = obj->base.dev; @@ -1192,7 +1211,7 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj, reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); mutex_unlock(&dev->struct_mutex); - ret = __wait_seqno(ring, seqno, reset_counter, true, NULL); + ret = __wait_seqno(ring, seqno, reset_counter, true, NULL, file->driver_priv); mutex_lock(&dev->struct_mutex); if (ret) return ret; @@ -1241,7 +1260,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, * We will repeat the flush holding the lock in the normal manner * to catch cases where we are gazumped. */ - ret = i915_gem_object_wait_rendering__nonblocking(obj, !write_domain); + ret = i915_gem_object_wait_rendering__nonblocking(obj, file, !write_domain); if (ret) goto unref; @@ -2162,6 +2181,7 @@ int __i915_add_request(struct intel_ring_buffer *ring, i915_queue_hangcheck(ring->dev); if (was_empty) { + cancel_delayed_work_sync(&dev_priv->mm.idle_work); queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, round_jiffies_up_relative(HZ)); @@ -2183,10 +2203,8 @@ i915_gem_request_remove_from_client(struct drm_i915_gem_request *request) return; spin_lock(&file_priv->mm.lock); - if (request->file_priv) { - list_del(&request->client_list); - request->file_priv = NULL; - } + list_del(&request->client_list); + request->file_priv = NULL; spin_unlock(&file_priv->mm.lock); } @@ -2450,57 +2468,53 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring) WARN_ON(i915_verify_lists(ring->dev)); } -void +bool i915_gem_retire_requests(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_ring_buffer *ring; + bool idle = true; int i; - for_each_ring(ring, dev_priv, i) + for_each_ring(ring, dev_priv, i) { i915_gem_retire_requests_ring(ring); + idle &= list_empty(&ring->request_list); + } + + if (idle) + mod_delayed_work(dev_priv->wq, + &dev_priv->mm.idle_work, + msecs_to_jiffies(100)); + + return idle; } static void i915_gem_retire_work_handler(struct work_struct *work) { - drm_i915_private_t *dev_priv; - struct drm_device *dev; - struct intel_ring_buffer *ring; + struct drm_i915_private *dev_priv = + container_of(work, typeof(*dev_priv), mm.retire_work.work); + struct drm_device *dev = dev_priv->dev; bool idle; - int i; - - dev_priv = container_of(work, drm_i915_private_t, - mm.retire_work.work); - dev = dev_priv->dev; /* Come back later if the device is busy... */ - if (!mutex_trylock(&dev->struct_mutex)) { - queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, - round_jiffies_up_relative(HZ)); - return; - } - - i915_gem_retire_requests(dev); - - /* Send a periodic flush down the ring so we don't hold onto GEM - * objects indefinitely. - */ - idle = true; - for_each_ring(ring, dev_priv, i) { - if (ring->gpu_caches_dirty) - i915_add_request(ring, NULL); - - idle &= list_empty(&ring->request_list); + idle = false; + if (mutex_trylock(&dev->struct_mutex)) { + idle = i915_gem_retire_requests(dev); + mutex_unlock(&dev->struct_mutex); } - - if (!dev_priv->ums.mm_suspended && !idle) + if (!idle) queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, round_jiffies_up_relative(HZ)); - if (idle) - intel_mark_idle(dev); +} - mutex_unlock(&dev->struct_mutex); +static void +i915_gem_idle_work_handler(struct work_struct *work) +{ + struct drm_i915_private *dev_priv = + container_of(work, typeof(*dev_priv), mm.idle_work.work); + + intel_mark_idle(dev_priv->dev); } /** @@ -2598,7 +2612,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) reset_counter = atomic_read(&dev_priv->gpu_error.reset_counter); mutex_unlock(&dev->struct_mutex); - ret = __wait_seqno(ring, seqno, reset_counter, true, timeout); + ret = __wait_seqno(ring, seqno, reset_counter, true, timeout, file->driver_priv); if (timeout) args->timeout_ns = timespec_to_ns(timeout); return ret; @@ -3809,7 +3823,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) if (seqno == 0) return 0; - ret = __wait_seqno(ring, seqno, reset_counter, true, NULL); + ret = __wait_seqno(ring, seqno, reset_counter, true, NULL, NULL); if (ret == 0) queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); @@ -4279,6 +4293,7 @@ i915_gem_idle(struct drm_device *dev) /* Cancel the retire work handler, which should be idle now. */ cancel_delayed_work_sync(&dev_priv->mm.retire_work); + cancel_delayed_work_sync(&dev_priv->mm.idle_work); return 0; } @@ -4612,6 +4627,8 @@ i915_gem_load(struct drm_device *dev) INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); INIT_DELAYED_WORK(&dev_priv->mm.retire_work, i915_gem_retire_work_handler); + INIT_DELAYED_WORK(&dev_priv->mm.idle_work, + i915_gem_idle_work_handler); init_waitqueue_head(&dev_priv->gpu_error.reset_queue); /* On GEN3 we really need to make sure the ARB C3 LP bit is set */ @@ -4836,6 +4853,8 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; + cancel_delayed_work_sync(&file_priv->mm.idle_work); + /* Clean up our request list when the client is going away, so that * later retire_requests won't dereference our soon-to-be-gone * file_priv. @@ -4853,6 +4872,38 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file) spin_unlock(&file_priv->mm.lock); } +static void +i915_gem_file_idle_work_handler(struct work_struct *work) +{ + struct drm_i915_file_private *file_priv = + container_of(work, typeof(*file_priv), mm.idle_work.work); + + atomic_set(&file_priv->rps_wait_boost, false); +} + +int i915_gem_open(struct drm_device *dev, struct drm_file *file) +{ + struct drm_i915_file_private *file_priv; + + DRM_DEBUG_DRIVER("\n"); + + file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); + if (!file_priv) + return -ENOMEM; + + file->driver_priv = file_priv; + file_priv->dev_priv = dev->dev_private; + + spin_lock_init(&file_priv->mm.lock); + INIT_LIST_HEAD(&file_priv->mm.request_list); + INIT_DELAYED_WORK(&file_priv->mm.idle_work, + i915_gem_file_idle_work_handler); + + idr_init(&file_priv->context_idr); + + return 0; +} + static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task) { if (!mutex_is_locked(mutex)) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 05c05a6a436..6ee557280e1 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -859,17 +859,6 @@ static void gen6_pm_rps_work(struct work_struct *work) gen6_set_rps(dev_priv->dev, new_delay); } - if (IS_VALLEYVIEW(dev_priv->dev)) { - /* - * On VLV, when we enter RC6 we may not be at the minimum - * voltage level, so arm a timer to check. It should only - * fire when there's activity or once after we've entered - * RC6, and then won't be re-armed until the next RPS interrupt. - */ - mod_delayed_work(dev_priv->wq, &dev_priv->rps.vlv_work, - msecs_to_jiffies(100)); - } - mutex_unlock(&dev_priv->rps.hw_lock); } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d9f698e9ab1..169d6825f9e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7726,6 +7726,9 @@ void intel_mark_idle(struct drm_device *dev) intel_decrease_pllclock(crtc); } + + if (dev_priv->info->gen >= 6) + gen6_rps_idle(dev->dev_private); } void intel_mark_fb_busy(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e6db0c67e0b..922c5d752cc 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -825,4 +825,7 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data, /* intel_tv.c */ void intel_tv_init(struct drm_device *dev); +void gen6_rps_idle(struct drm_i915_private *dev_priv); +void gen6_rps_boost(struct drm_i915_private *dev_priv); + #endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9753bd9591e..ca063c25ad3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3345,6 +3345,26 @@ void gen6_set_rps(struct drm_device *dev, u8 val) trace_intel_gpu_freq_change(val * 50); } +void gen6_rps_idle(struct drm_i915_private *dev_priv) +{ + mutex_lock(&dev_priv->rps.hw_lock); + if (dev_priv->info->is_valleyview) + valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_delay); + else + gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay); + mutex_unlock(&dev_priv->rps.hw_lock); +} + +void gen6_rps_boost(struct drm_i915_private *dev_priv) +{ + mutex_lock(&dev_priv->rps.hw_lock); + if (dev_priv->info->is_valleyview) + valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_delay); + else + gen6_set_rps(dev_priv->dev, dev_priv->rps.max_delay); + mutex_unlock(&dev_priv->rps.hw_lock); +} + /* * Wait until the previous freq change has completed, * or the timeout elapsed, and then update our notion @@ -3734,24 +3754,6 @@ int valleyview_rps_min_freq(struct drm_i915_private *dev_priv) return vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM) & 0xff; } -static void vlv_rps_timer_work(struct work_struct *work) -{ - drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, - rps.vlv_work.work); - - /* - * Timer fired, we must be idle. Drop to min voltage state. - * Note: we use RPe here since it should match the - * Vmin we were shooting for. That should give us better - * perf when we come back out of RC6 than if we used the - * min freq available. - */ - mutex_lock(&dev_priv->rps.hw_lock); - if (dev_priv->rps.cur_delay > dev_priv->rps.rpe_delay) - valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay); - mutex_unlock(&dev_priv->rps.hw_lock); -} - static void valleyview_setup_pctx(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3894,8 +3896,6 @@ static void valleyview_enable_rps(struct drm_device *dev) dev_priv->rps.rpe_delay), dev_priv->rps.rpe_delay); - INIT_DELAYED_WORK(&dev_priv->rps.vlv_work, vlv_rps_timer_work); - valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay); gen6_enable_rps_interrupts(dev); @@ -4635,8 +4635,6 @@ void intel_disable_gt_powersave(struct drm_device *dev) } else if (INTEL_INFO(dev)->gen >= 6) { cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work); cancel_work_sync(&dev_priv->rps.work); - if (IS_VALLEYVIEW(dev)) - cancel_delayed_work_sync(&dev_priv->rps.vlv_work); mutex_lock(&dev_priv->rps.hw_lock); if (IS_VALLEYVIEW(dev)) valleyview_disable_rps(dev); -- cgit v1.2.3-70-g09d2 From dd75fdc8c69587c91bd68a6ed7c726b5e70f9399 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 25 Sep 2013 17:34:57 +0100 Subject: drm/i915: Tweak RPS thresholds to more aggressively downclock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After applying wait-boost we often find ourselves stuck at higher clocks than required. The current threshold value requires the GPU to be continuously and completely idle for 313ms before it is dropped by one bin. Conversely, we require the GPU to be busy for an average of 90% over a 84ms period before we upclock. So the current thresholds almost never downclock the GPU, and respond very slowly to sudden demands for more power. It is easy to observe that we currently lock into the wrong bin and both underperform in benchmarks and consume more power than optimal (just by repeating the task and measuring the different results). An alternative approach, as discussed in the bspec, is to use a continuous threshold for upclocking, and an average value for downclocking. This is good for quickly detecting and reacting to state changes within a frame, however it fails with the common throttling method of waiting upon the outstanding frame - at least it is difficult to choose a threshold that works well at 15,000fps and at 60fps. So continue to use average busy/idle loads to determine frequency change. v2: Use 3 power zones to keep frequencies low in steady-state mostly idle (e.g. scrolling, interactive 2D drawing), and frequencies high for demanding games. In between those end-states, we use a fast-reclocking algorithm to converge more quickly on the desired bin. v3: Bug fixes - make sure we reset adj after switching power zones. v4: Tune - drop the continuous busy thresholds as it prevents us from choosing the right frequency for glxgears style swap benchmarks. Instead the goal is to be able to find the right clocks irrespective of the wait-boost. Signed-off-by: Chris Wilson Cc: Kenneth Graunke Cc: Stéphane Marchesin Cc: Owen Taylor Cc: "Meng, Mengmeng" Cc: "Zhuang, Lena" Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 5 ++ drivers/gpu/drm/i915/i915_irq.c | 46 ++++++++++---- drivers/gpu/drm/i915/i915_reg.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 137 ++++++++++++++++++++++++++++++---------- 4 files changed, 143 insertions(+), 47 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d1c6b92edae..5118ac300c4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -850,8 +850,13 @@ struct intel_gen6_power_mgmt { u8 min_delay; u8 max_delay; u8 rpe_delay; + u8 rp1_delay; + u8 rp0_delay; u8 hw_max; + int last_adj; + enum { LOW_POWER, BETWEEN, HIGH_POWER } power; + struct delayed_work delayed_resume_work; /* diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 6ee557280e1..418ad642c74 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -818,7 +818,7 @@ static void gen6_pm_rps_work(struct work_struct *work) drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, rps.work); u32 pm_iir; - u8 new_delay; + int new_delay, adj; spin_lock_irq(&dev_priv->irq_lock); pm_iir = dev_priv->rps.pm_iir; @@ -835,29 +835,49 @@ static void gen6_pm_rps_work(struct work_struct *work) mutex_lock(&dev_priv->rps.hw_lock); + adj = dev_priv->rps.last_adj; if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) { - new_delay = dev_priv->rps.cur_delay + 1; + if (adj > 0) + adj *= 2; + else + adj = 1; + new_delay = dev_priv->rps.cur_delay + adj; /* * For better performance, jump directly * to RPe if we're below it. */ - if (IS_VALLEYVIEW(dev_priv->dev) && - dev_priv->rps.cur_delay < dev_priv->rps.rpe_delay) + if (new_delay < dev_priv->rps.rpe_delay) + new_delay = dev_priv->rps.rpe_delay; + } else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) { + if (dev_priv->rps.cur_delay > dev_priv->rps.rpe_delay) new_delay = dev_priv->rps.rpe_delay; - } else - new_delay = dev_priv->rps.cur_delay - 1; + else + new_delay = dev_priv->rps.min_delay; + adj = 0; + } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) { + if (adj < 0) + adj *= 2; + else + adj = -1; + new_delay = dev_priv->rps.cur_delay + adj; + } else { /* unknown event */ + new_delay = dev_priv->rps.cur_delay; + } /* sysfs frequency interfaces may have snuck in while servicing the * interrupt */ - if (new_delay >= dev_priv->rps.min_delay && - new_delay <= dev_priv->rps.max_delay) { - if (IS_VALLEYVIEW(dev_priv->dev)) - valleyview_set_rps(dev_priv->dev, new_delay); - else - gen6_set_rps(dev_priv->dev, new_delay); - } + if (new_delay < (int)dev_priv->rps.min_delay) + new_delay = dev_priv->rps.min_delay; + if (new_delay > (int)dev_priv->rps.max_delay) + new_delay = dev_priv->rps.max_delay; + dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay; + + if (IS_VALLEYVIEW(dev_priv->dev)) + valleyview_set_rps(dev_priv->dev, new_delay); + else + gen6_set_rps(dev_priv->dev, new_delay); mutex_unlock(&dev_priv->rps.hw_lock); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 96fd2ce6aa0..daaabe788f2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4687,7 +4687,7 @@ #define GEN6_RP_UP_IDLE_MIN (0x1<<3) #define GEN6_RP_UP_BUSY_AVG (0x2<<3) #define GEN6_RP_UP_BUSY_CONT (0x4<<3) -#define GEN7_RP_DOWN_IDLE_AVG (0x2<<0) +#define GEN6_RP_DOWN_IDLE_AVG (0x2<<0) #define GEN6_RP_DOWN_IDLE_CONT (0x1<<0) #define GEN6_RP_UP_THRESHOLD 0xA02C #define GEN6_RP_DOWN_THRESHOLD 0xA030 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ca063c25ad3..b08a96cd9c9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3312,6 +3312,98 @@ static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 *val) return limits; } +static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) +{ + int new_power; + + new_power = dev_priv->rps.power; + switch (dev_priv->rps.power) { + case LOW_POWER: + if (val > dev_priv->rps.rpe_delay + 1 && val > dev_priv->rps.cur_delay) + new_power = BETWEEN; + break; + + case BETWEEN: + if (val <= dev_priv->rps.rpe_delay && val < dev_priv->rps.cur_delay) + new_power = LOW_POWER; + else if (val >= dev_priv->rps.rp0_delay && val > dev_priv->rps.cur_delay) + new_power = HIGH_POWER; + break; + + case HIGH_POWER: + if (val < (dev_priv->rps.rp1_delay + dev_priv->rps.rp0_delay) >> 1 && val < dev_priv->rps.cur_delay) + new_power = BETWEEN; + break; + } + /* Max/min bins are special */ + if (val == dev_priv->rps.min_delay) + new_power = LOW_POWER; + if (val == dev_priv->rps.max_delay) + new_power = HIGH_POWER; + if (new_power == dev_priv->rps.power) + return; + + /* Note the units here are not exactly 1us, but 1280ns. */ + switch (new_power) { + case LOW_POWER: + /* Upclock if more than 95% busy over 16ms */ + I915_WRITE(GEN6_RP_UP_EI, 12500); + I915_WRITE(GEN6_RP_UP_THRESHOLD, 11800); + + /* Downclock if less than 85% busy over 32ms */ + I915_WRITE(GEN6_RP_DOWN_EI, 25000); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 21250); + + I915_WRITE(GEN6_RP_CONTROL, + GEN6_RP_MEDIA_TURBO | + GEN6_RP_MEDIA_HW_NORMAL_MODE | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_ENABLE | + GEN6_RP_UP_BUSY_AVG | + GEN6_RP_DOWN_IDLE_AVG); + break; + + case BETWEEN: + /* Upclock if more than 90% busy over 13ms */ + I915_WRITE(GEN6_RP_UP_EI, 10250); + I915_WRITE(GEN6_RP_UP_THRESHOLD, 9225); + + /* Downclock if less than 75% busy over 32ms */ + I915_WRITE(GEN6_RP_DOWN_EI, 25000); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 18750); + + I915_WRITE(GEN6_RP_CONTROL, + GEN6_RP_MEDIA_TURBO | + GEN6_RP_MEDIA_HW_NORMAL_MODE | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_ENABLE | + GEN6_RP_UP_BUSY_AVG | + GEN6_RP_DOWN_IDLE_AVG); + break; + + case HIGH_POWER: + /* Upclock if more than 85% busy over 10ms */ + I915_WRITE(GEN6_RP_UP_EI, 8000); + I915_WRITE(GEN6_RP_UP_THRESHOLD, 6800); + + /* Downclock if less than 60% busy over 32ms */ + I915_WRITE(GEN6_RP_DOWN_EI, 25000); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 15000); + + I915_WRITE(GEN6_RP_CONTROL, + GEN6_RP_MEDIA_TURBO | + GEN6_RP_MEDIA_HW_NORMAL_MODE | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_ENABLE | + GEN6_RP_UP_BUSY_AVG | + GEN6_RP_DOWN_IDLE_AVG); + break; + } + + dev_priv->rps.power = new_power; + dev_priv->rps.last_adj = 0; +} + void gen6_set_rps(struct drm_device *dev, u8 val) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3324,6 +3416,8 @@ void gen6_set_rps(struct drm_device *dev, u8 val) if (val == dev_priv->rps.cur_delay) return; + gen6_set_rps_thresholds(dev_priv, val); + if (IS_HASWELL(dev)) I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(val)); @@ -3352,6 +3446,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv) valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_delay); else gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay); + dev_priv->rps.last_adj = 0; mutex_unlock(&dev_priv->rps.hw_lock); } @@ -3362,6 +3457,7 @@ void gen6_rps_boost(struct drm_i915_private *dev_priv) valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_delay); else gen6_set_rps(dev_priv->dev, dev_priv->rps.max_delay); + dev_priv->rps.last_adj = 0; mutex_unlock(&dev_priv->rps.hw_lock); } @@ -3546,7 +3642,10 @@ static void gen6_enable_rps(struct drm_device *dev) /* In units of 50MHz */ dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff; - dev_priv->rps.min_delay = (rp_state_cap & 0xff0000) >> 16; + dev_priv->rps.min_delay = (rp_state_cap >> 16) & 0xff; + dev_priv->rps.rp1_delay = (rp_state_cap >> 8) & 0xff; + dev_priv->rps.rp0_delay = (rp_state_cap >> 0) & 0xff; + dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay; dev_priv->rps.cur_delay = 0; /* disable the counters and set deterministic thresholds */ @@ -3594,38 +3693,9 @@ static void gen6_enable_rps(struct drm_device *dev) GEN6_RC_CTL_EI_MODE(1) | GEN6_RC_CTL_HW_ENABLE); - if (IS_HASWELL(dev)) { - I915_WRITE(GEN6_RPNSWREQ, - HSW_FREQUENCY(10)); - I915_WRITE(GEN6_RC_VIDEO_FREQ, - HSW_FREQUENCY(12)); - } else { - I915_WRITE(GEN6_RPNSWREQ, - GEN6_FREQUENCY(10) | - GEN6_OFFSET(0) | - GEN6_AGGRESSIVE_TURBO); - I915_WRITE(GEN6_RC_VIDEO_FREQ, - GEN6_FREQUENCY(12)); - } - - I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); - I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, - dev_priv->rps.max_delay << 24 | - dev_priv->rps.min_delay << 16); - - I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); - I915_WRITE(GEN6_RP_UP_EI, 66000); - I915_WRITE(GEN6_RP_DOWN_EI, 350000); - + /* Power down if completely idle for over 50ms */ + I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 50000); I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); - I915_WRITE(GEN6_RP_CONTROL, - GEN6_RP_MEDIA_TURBO | - GEN6_RP_MEDIA_HW_NORMAL_MODE | - GEN6_RP_MEDIA_IS_GFX | - GEN6_RP_ENABLE | - GEN6_RP_UP_BUSY_AVG | - (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT)); ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0); if (!ret) { @@ -3641,7 +3711,8 @@ static void gen6_enable_rps(struct drm_device *dev) DRM_DEBUG_DRIVER("Failed to set the min frequency\n"); } - gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8); + dev_priv->rps.power = HIGH_POWER; /* force a reset */ + gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay); gen6_enable_rps_interrupts(dev); -- cgit v1.2.3-70-g09d2 From 5380e9293b865d88de04de6e5324726d8c5b53c9 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 4 Oct 2013 14:53:36 +0300 Subject: drm: Collect per-crtc vblank stuff to a struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_vblank_init() is too ugly. Make it a bit easier on the eye by collecting all the per-crtc vblank counters, timestamps etc. to a structure and just allocate an array of those. Signed-off-by: Ville Syrjälä Reviewed-by: Daniel Vetter Reviewed-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_info.c | 6 +- drivers/gpu/drm/drm_irq.c | 138 +++++++++++++------------------------ drivers/gpu/drm/gma500/psb_irq.c | 22 +++--- drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/omapdrm/omap_irq.c | 6 +- include/drm/drmP.h | 26 ++++--- 6 files changed, 81 insertions(+), 119 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 53298320080..7d5a152eeb0 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c @@ -163,13 +163,13 @@ int drm_vblank_info(struct seq_file *m, void *data) mutex_lock(&dev->struct_mutex); for (crtc = 0; crtc < dev->num_crtcs; crtc++) { seq_printf(m, "CRTC %d enable: %d\n", - crtc, atomic_read(&dev->vblank_refcount[crtc])); + crtc, atomic_read(&dev->vblank[crtc].refcount)); seq_printf(m, "CRTC %d counter: %d\n", crtc, drm_vblank_count(dev, crtc)); seq_printf(m, "CRTC %d last wait: %d\n", - crtc, dev->last_vblank_wait[crtc]); + crtc, dev->vblank[crtc].last_wait); seq_printf(m, "CRTC %d in modeset: %d\n", - crtc, dev->vblank_inmodeset[crtc]); + crtc, dev->vblank[crtc].inmodeset); } mutex_unlock(&dev->struct_mutex); return 0; diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 49680a8ab96..dea859f2003 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -43,9 +43,8 @@ #include /* Access macro for slots in vblank timestamp ringbuffer. */ -#define vblanktimestamp(dev, crtc, count) ( \ - (dev)->_vblank_time[(crtc) * DRM_VBLANKTIME_RBSIZE + \ - ((count) % DRM_VBLANKTIME_RBSIZE)]) +#define vblanktimestamp(dev, crtc, count) \ + ((dev)->vblank[crtc].time[(count) % DRM_VBLANKTIME_RBSIZE]) /* Retry timestamp calculation up to 3 times to satisfy * drm_timestamp_precision before giving up. @@ -89,8 +88,7 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, */ static void clear_vblank_timestamps(struct drm_device *dev, int crtc) { - memset(&dev->_vblank_time[crtc * DRM_VBLANKTIME_RBSIZE], 0, - DRM_VBLANKTIME_RBSIZE * sizeof(struct timeval)); + memset(dev->vblank[crtc].time, 0, sizeof(dev->vblank[crtc].time)); } /* @@ -115,7 +113,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) spin_lock_irqsave(&dev->vblank_time_lock, irqflags); dev->driver->disable_vblank(dev, crtc); - dev->vblank_enabled[crtc] = false; + dev->vblank[crtc].enabled = false; /* No further vblank irq's will be processed after * this point. Get current hardware vblank count and @@ -130,9 +128,9 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) * delayed gpu counter increment. */ do { - dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); + dev->vblank[crtc].last = dev->driver->get_vblank_counter(dev, crtc); vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); - } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc); + } while (dev->vblank[crtc].last != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc); if (!count) vblrc = 0; @@ -140,7 +138,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) /* Compute time difference to stored timestamp of last vblank * as updated by last invocation of drm_handle_vblank() in vblank irq. */ - vblcount = atomic_read(&dev->_vblank_count[crtc]); + vblcount = atomic_read(&dev->vblank[crtc].count); diff_ns = timeval_to_ns(&tvblank) - timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); @@ -157,7 +155,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) * hope for the best. */ if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) { - atomic_inc(&dev->_vblank_count[crtc]); + atomic_inc(&dev->vblank[crtc].count); smp_mb__after_atomic_inc(); } @@ -178,8 +176,8 @@ static void vblank_disable_fn(unsigned long arg) for (i = 0; i < dev->num_crtcs; i++) { spin_lock_irqsave(&dev->vbl_lock, irqflags); - if (atomic_read(&dev->vblank_refcount[i]) == 0 && - dev->vblank_enabled[i]) { + if (atomic_read(&dev->vblank[i].refcount) == 0 && + dev->vblank[i].enabled) { DRM_DEBUG("disabling vblank on crtc %d\n", i); vblank_disable_and_save(dev, i); } @@ -197,14 +195,7 @@ void drm_vblank_cleanup(struct drm_device *dev) vblank_disable_fn((unsigned long)dev); - kfree(dev->vbl_queue); - kfree(dev->_vblank_count); - kfree(dev->vblank_refcount); - kfree(dev->vblank_enabled); - kfree(dev->last_vblank); - kfree(dev->last_vblank_wait); - kfree(dev->vblank_inmodeset); - kfree(dev->_vblank_time); + kfree(dev->vblank); dev->num_crtcs = 0; } @@ -221,40 +212,12 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) dev->num_crtcs = num_crtcs; - dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs, - GFP_KERNEL); - if (!dev->vbl_queue) + dev->vblank = kcalloc(num_crtcs, sizeof(*dev->vblank), GFP_KERNEL); + if (!dev->vblank) goto err; - dev->_vblank_count = kmalloc(sizeof(atomic_t) * num_crtcs, GFP_KERNEL); - if (!dev->_vblank_count) - goto err; - - dev->vblank_refcount = kmalloc(sizeof(atomic_t) * num_crtcs, - GFP_KERNEL); - if (!dev->vblank_refcount) - goto err; - - dev->vblank_enabled = kcalloc(num_crtcs, sizeof(bool), GFP_KERNEL); - if (!dev->vblank_enabled) - goto err; - - dev->last_vblank = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL); - if (!dev->last_vblank) - goto err; - - dev->last_vblank_wait = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL); - if (!dev->last_vblank_wait) - goto err; - - dev->vblank_inmodeset = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL); - if (!dev->vblank_inmodeset) - goto err; - - dev->_vblank_time = kcalloc(num_crtcs * DRM_VBLANKTIME_RBSIZE, - sizeof(struct timeval), GFP_KERNEL); - if (!dev->_vblank_time) - goto err; + for (i = 0; i < num_crtcs; i++) + init_waitqueue_head(&dev->vblank[i].queue); DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n"); @@ -264,13 +227,6 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) else DRM_INFO("No driver support for vblank timestamp query.\n"); - /* Zero per-crtc vblank stuff */ - for (i = 0; i < num_crtcs; i++) { - init_waitqueue_head(&dev->vbl_queue[i]); - atomic_set(&dev->_vblank_count[i], 0); - atomic_set(&dev->vblank_refcount[i], 0); - } - dev->vblank_disable_allowed = false; return 0; @@ -411,9 +367,9 @@ int drm_irq_uninstall(struct drm_device *dev) if (dev->num_crtcs) { spin_lock_irqsave(&dev->vbl_lock, irqflags); for (i = 0; i < dev->num_crtcs; i++) { - DRM_WAKEUP(&dev->vbl_queue[i]); - dev->vblank_enabled[i] = false; - dev->last_vblank[i] = + DRM_WAKEUP(&dev->vblank[i].queue); + dev->vblank[i].enabled = false; + dev->vblank[i].last = dev->driver->get_vblank_counter(dev, i); } spin_unlock_irqrestore(&dev->vbl_lock, irqflags); @@ -796,7 +752,7 @@ EXPORT_SYMBOL(drm_get_last_vbltimestamp); */ u32 drm_vblank_count(struct drm_device *dev, int crtc) { - return atomic_read(&dev->_vblank_count[crtc]); + return atomic_read(&dev->vblank[crtc].count); } EXPORT_SYMBOL(drm_vblank_count); @@ -825,10 +781,10 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, * a seqlock. */ do { - cur_vblank = atomic_read(&dev->_vblank_count[crtc]); + cur_vblank = atomic_read(&dev->vblank[crtc].count); *vblanktime = vblanktimestamp(dev, crtc, cur_vblank); smp_rmb(); - } while (cur_vblank != atomic_read(&dev->_vblank_count[crtc])); + } while (cur_vblank != atomic_read(&dev->vblank[crtc].count)); return cur_vblank; } @@ -915,12 +871,12 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc)); /* Deal with counter wrap */ - diff = cur_vblank - dev->last_vblank[crtc]; - if (cur_vblank < dev->last_vblank[crtc]) { + diff = cur_vblank - dev->vblank[crtc].last; + if (cur_vblank < dev->vblank[crtc].last) { diff += dev->max_vblank_count; DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n", - crtc, dev->last_vblank[crtc], cur_vblank, diff); + crtc, dev->vblank[crtc].last, cur_vblank, diff); } DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", @@ -931,12 +887,12 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) * reinitialize delayed at next vblank interrupt in that case. */ if (rc) { - tslot = atomic_read(&dev->_vblank_count[crtc]) + diff; + tslot = atomic_read(&dev->vblank[crtc].count) + diff; vblanktimestamp(dev, crtc, tslot) = t_vblank; } smp_mb__before_atomic_inc(); - atomic_add(diff, &dev->_vblank_count[crtc]); + atomic_add(diff, &dev->vblank[crtc].count); smp_mb__after_atomic_inc(); } @@ -958,9 +914,9 @@ int drm_vblank_get(struct drm_device *dev, int crtc) spin_lock_irqsave(&dev->vbl_lock, irqflags); /* Going from 0->1 means we have to enable interrupts again */ - if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { + if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) { spin_lock_irqsave(&dev->vblank_time_lock, irqflags2); - if (!dev->vblank_enabled[crtc]) { + if (!dev->vblank[crtc].enabled) { /* Enable vblank irqs under vblank_time_lock protection. * All vblank count & timestamp updates are held off * until we are done reinitializing master counter and @@ -971,16 +927,16 @@ int drm_vblank_get(struct drm_device *dev, int crtc) DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); if (ret) - atomic_dec(&dev->vblank_refcount[crtc]); + atomic_dec(&dev->vblank[crtc].refcount); else { - dev->vblank_enabled[crtc] = true; + dev->vblank[crtc].enabled = true; drm_update_vblank_count(dev, crtc); } } spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2); } else { - if (!dev->vblank_enabled[crtc]) { - atomic_dec(&dev->vblank_refcount[crtc]); + if (!dev->vblank[crtc].enabled) { + atomic_dec(&dev->vblank[crtc].refcount); ret = -EINVAL; } } @@ -1000,10 +956,10 @@ EXPORT_SYMBOL(drm_vblank_get); */ void drm_vblank_put(struct drm_device *dev, int crtc) { - BUG_ON(atomic_read(&dev->vblank_refcount[crtc]) == 0); + BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0); /* Last user schedules interrupt disable */ - if (atomic_dec_and_test(&dev->vblank_refcount[crtc]) && + if (atomic_dec_and_test(&dev->vblank[crtc].refcount) && (drm_vblank_offdelay > 0)) mod_timer(&dev->vblank_disable_timer, jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000)); @@ -1026,7 +982,7 @@ void drm_vblank_off(struct drm_device *dev, int crtc) spin_lock_irqsave(&dev->vbl_lock, irqflags); vblank_disable_and_save(dev, crtc); - DRM_WAKEUP(&dev->vbl_queue[crtc]); + DRM_WAKEUP(&dev->vblank[crtc].queue); /* Send any queued vblank events, lest the natives grow disquiet */ seq = drm_vblank_count_and_time(dev, crtc, &now); @@ -1068,10 +1024,10 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) * to avoid corrupting the count if multiple, mismatch calls occur), * so that interrupts remain enabled in the interim. */ - if (!dev->vblank_inmodeset[crtc]) { - dev->vblank_inmodeset[crtc] = 0x1; + if (!dev->vblank[crtc].inmodeset) { + dev->vblank[crtc].inmodeset = 0x1; if (drm_vblank_get(dev, crtc) == 0) - dev->vblank_inmodeset[crtc] |= 0x2; + dev->vblank[crtc].inmodeset |= 0x2; } } EXPORT_SYMBOL(drm_vblank_pre_modeset); @@ -1084,15 +1040,15 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc) if (!dev->num_crtcs) return; - if (dev->vblank_inmodeset[crtc]) { + if (dev->vblank[crtc].inmodeset) { spin_lock_irqsave(&dev->vbl_lock, irqflags); dev->vblank_disable_allowed = true; spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - if (dev->vblank_inmodeset[crtc] & 0x2) + if (dev->vblank[crtc].inmodeset & 0x2) drm_vblank_put(dev, crtc); - dev->vblank_inmodeset[crtc] = 0; + dev->vblank[crtc].inmodeset = 0; } } EXPORT_SYMBOL(drm_vblank_post_modeset); @@ -1289,8 +1245,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data, DRM_DEBUG("waiting on vblank count %d, crtc %d\n", vblwait->request.sequence, crtc); - dev->last_vblank_wait[crtc] = vblwait->request.sequence; - DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, + dev->vblank[crtc].last_wait = vblwait->request.sequence; + DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * DRM_HZ, (((drm_vblank_count(dev, crtc) - vblwait->request.sequence) <= (1 << 23)) || !dev->irq_enabled)); @@ -1368,7 +1324,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) spin_lock_irqsave(&dev->vblank_time_lock, irqflags); /* Vblank irq handling disabled. Nothing to do. */ - if (!dev->vblank_enabled[crtc]) { + if (!dev->vblank[crtc].enabled) { spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); return false; } @@ -1378,7 +1334,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) */ /* Get current timestamp and count. */ - vblcount = atomic_read(&dev->_vblank_count[crtc]); + vblcount = atomic_read(&dev->vblank[crtc].count); drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ); /* Compute time difference to timestamp of last vblank */ @@ -1402,14 +1358,14 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) * the timestamp computed above. */ smp_mb__before_atomic_inc(); - atomic_inc(&dev->_vblank_count[crtc]); + atomic_inc(&dev->vblank[crtc].count); smp_mb__after_atomic_inc(); } else { DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", crtc, (int) diff_ns); } - DRM_WAKEUP(&dev->vbl_queue[crtc]); + DRM_WAKEUP(&dev->vblank[crtc].queue); drm_handle_vblank_events(dev, crtc); spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index 029eccf3013..ba4830342d3 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -271,15 +271,15 @@ void psb_irq_preinstall(struct drm_device *dev) if (gma_power_is_on(dev)) PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - if (dev->vblank_enabled[0]) + if (dev->vblank[0].enabled) dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; - if (dev->vblank_enabled[1]) + if (dev->vblank[1].enabled) dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; /* FIXME: Handle Medfield irq mask - if (dev->vblank_enabled[1]) + if (dev->vblank[1].enabled) dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG; - if (dev->vblank_enabled[2]) + if (dev->vblank[2].enabled) dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; */ @@ -305,17 +305,17 @@ int psb_irq_postinstall(struct drm_device *dev) PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - if (dev->vblank_enabled[0]) + if (dev->vblank[0].enabled) psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); else psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - if (dev->vblank_enabled[1]) + if (dev->vblank[1].enabled) psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); else psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - if (dev->vblank_enabled[2]) + if (dev->vblank[2].enabled) psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); else psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); @@ -339,13 +339,13 @@ void psb_irq_uninstall(struct drm_device *dev) PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - if (dev->vblank_enabled[0]) + if (dev->vblank[0].enabled) psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - if (dev->vblank_enabled[1]) + if (dev->vblank[1].enabled) psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - if (dev->vblank_enabled[2]) + if (dev->vblank[2].enabled) psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | @@ -456,7 +456,7 @@ static int psb_vblank_do_wait(struct drm_device *dev, { unsigned int cur_vblank; int ret = 0; - DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, + DRM_WAIT_ON(ret, dev->vblank.queue, 3 * DRM_HZ, (((cur_vblank = atomic_read(counter)) - *sequence) <= (1 << 23))); *sequence = cur_vblank; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 4692f8cb772..3907c60a72d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5340,7 +5340,7 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) spin_lock_irqsave(&dev->vbl_lock, irqflags); for_each_pipe(p) if (p != PIPE_A) - dev->last_vblank[p] = 0; + dev->vblank[p].last = 0; spin_unlock_irqrestore(&dev->vbl_lock, irqflags); } } diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c index 3cbe92c72fd..261b227e469 100644 --- a/drivers/gpu/drm/omapdrm/omap_irq.c +++ b/drivers/gpu/drm/omapdrm/omap_irq.c @@ -307,9 +307,9 @@ int omap_drm_irq_uninstall(struct drm_device *dev) if (dev->num_crtcs) { spin_lock_irqsave(&dev->vbl_lock, irqflags); for (i = 0; i < dev->num_crtcs; i++) { - DRM_WAKEUP(&dev->vbl_queue[i]); - dev->vblank_enabled[i] = false; - dev->last_vblank[i] = + DRM_WAKEUP(&dev->vblank[i].queue); + dev->vblank[i].enabled = false; + dev->vblank[i].last = dev->driver->get_vblank_counter(dev, i); } spin_unlock_irqrestore(&dev->vbl_lock, irqflags); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 2d390abbf55..7198febd9d8 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1078,6 +1078,19 @@ struct drm_pending_vblank_event { struct drm_event_vblank event; }; +struct drm_vblank_crtc { + wait_queue_head_t queue; /**< VBLANK wait queue */ + struct timeval time[DRM_VBLANKTIME_RBSIZE]; /**< timestamp of current count */ + atomic_t count; /**< number of VBLANK interrupts */ + atomic_t refcount; /* number of users of vblank interruptsper crtc */ + u32 last; /* protected by dev->vbl_lock, used */ + /* for wraparound handling */ + u32 last_wait; /* Last vblank seqno waited per CRTC */ + unsigned int inmodeset; /* Display driver is setting mode */ + bool enabled; /* so we don't call enable more than + once per disable */ +}; + /** * DRM device structure. This structure represent a complete card that * may contain multiple heads. @@ -1153,18 +1166,11 @@ struct drm_device { */ bool vblank_disable_allowed; - wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */ - atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */ - struct timeval *_vblank_time; /**< timestamp of current vblank_count (drivers must alloc right number of fields) */ + /* array of size num_crtcs */ + struct drm_vblank_crtc *vblank; + spinlock_t vblank_time_lock; /**< Protects vblank count and time updates during vblank enable/disable */ spinlock_t vbl_lock; - atomic_t *vblank_refcount; /* number of users of vblank interruptsper crtc */ - u32 *last_vblank; /* protected by dev->vbl_lock, used */ - /* for wraparound handling */ - bool *vblank_enabled; /* so we don't call enable more than - once per disable */ - unsigned int *vblank_inmodeset; /* Display driver is setting mode */ - u32 *last_vblank_wait; /* Last vblank seqno waited per CRTC */ struct timer_list vblank_disable_timer; u32 max_vblank_count; /**< size of vblank counter register */ -- cgit v1.2.3-70-g09d2 From 1dba99f495fb2b8712d83f53a769a7393ea127d3 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 1 Oct 2013 18:02:18 +0300 Subject: drm/i915: Rename intel_flush_display_plane to intel_flush_primary_plane MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The intel_flush_primary_plane name actually tells us which plane we're talking about. Also reorganize the internals a bit and add a missing POSTING_READ() to make sure the hardware has seen the changes by the time we return from the function. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 16 ++++++++-------- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/i915/intel_tv.c | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index fdaa672f148..985c389e14e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1812,13 +1812,13 @@ static void intel_disable_pipe(struct drm_i915_private *dev_priv, * Plane regs are double buffered, going from enabled->disabled needs a * trigger in order to latch. The display address reg provides this. */ -void intel_flush_display_plane(struct drm_i915_private *dev_priv, - enum plane plane) +void intel_flush_primary_plane(struct drm_i915_private *dev_priv, + enum plane plane) { - if (dev_priv->info->gen >= 4) - I915_WRITE(DSPSURF(plane), I915_READ(DSPSURF(plane))); - else - I915_WRITE(DSPADDR(plane), I915_READ(DSPADDR(plane))); + u32 reg = dev_priv->info->gen >= 4 ? DSPSURF(plane) : DSPADDR(plane); + + I915_WRITE(reg, I915_READ(reg)); + POSTING_READ(reg); } /** @@ -1848,7 +1848,7 @@ static void intel_enable_plane(struct drm_i915_private *dev_priv, return; I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE); - intel_flush_display_plane(dev_priv, plane); + intel_flush_primary_plane(dev_priv, plane); intel_wait_for_vblank(dev_priv->dev, pipe); } @@ -1876,7 +1876,7 @@ static void intel_disable_plane(struct drm_i915_private *dev_priv, return; I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE); - intel_flush_display_plane(dev_priv, plane); + intel_flush_primary_plane(dev_priv, plane); intel_wait_for_vblank(dev_priv->dev, pipe); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 55c8bc4b7d9..dea20ce65e5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -811,7 +811,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob); /* intel_sprite.c */ int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane); -void intel_flush_display_plane(struct drm_i915_private *dev_priv, +void intel_flush_primary_plane(struct drm_i915_private *dev_priv, enum plane plane); void intel_plane_restore(struct drm_plane *plane); void intel_plane_disable(struct drm_plane *plane); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 008ec0bb017..da24825acc8 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4773,7 +4773,7 @@ static void g4x_disable_trickle_feed(struct drm_device *dev) I915_WRITE(DSPCNTR(pipe), I915_READ(DSPCNTR(pipe)) | DISPPLANE_TRICKLE_FEED_DISABLE); - intel_flush_display_plane(dev_priv, pipe); + intel_flush_primary_plane(dev_priv, pipe); } } diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index d61aec23a52..18c406246a2 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1094,7 +1094,7 @@ static void intel_tv_mode_set(struct intel_encoder *encoder) unsigned int xsize, ysize; /* Pipe must be off here */ I915_WRITE(dspcntr_reg, dspcntr & ~DISPLAY_PLANE_ENABLE); - intel_flush_display_plane(dev_priv, intel_crtc->plane); + intel_flush_primary_plane(dev_priv, intel_crtc->plane); /* Wait for vblank for the disable to take effect */ if (IS_GEN2(dev)) @@ -1123,7 +1123,7 @@ static void intel_tv_mode_set(struct intel_encoder *encoder) I915_WRITE(pipeconf_reg, pipeconf); I915_WRITE(dspcntr_reg, dspcntr); - intel_flush_display_plane(dev_priv, intel_crtc->plane); + intel_flush_primary_plane(dev_priv, intel_crtc->plane); } j = 0; -- cgit v1.2.3-70-g09d2 From eda796422aeb23a155b92ddc89cd70b9beffbad6 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 7 Oct 2013 17:15:48 -0300 Subject: drm/i915: Use the real cpu max frequency for ring scaling The policy's max frequency is not equal to the CPU's max frequency. The ring frequency is derived from the CPU frequency, and not the policy frequency. One example of how this may differ through sysfs. If the sysfs max frequency is modified, that will be used for the max ring frequency calculation. (/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq). As far as I know, no current governor uses anything but max as the default, but in theory, they could. Similarly distributions might set policy as part of their init process. It's ideal to use the real frequency because when we're currently scaled up on the GPU. In this case we likely want to race to idle, and using a less than max ring frequency is non-optimal for this situation. AFAIK, this patch should have no impact on a majority of people. This behavior hasn't been changed since it was first introduced: commit 23b2f8bb92feb83127679c53633def32d3108e70 Author: Jesse Barnes Date: Tue Jun 28 13:04:16 2011 -0700 drm/i915: load a ring frequency scaling table v3 CC: Jesse Barnes Signed-off-by: Ben Widawsky Reviewed-by: Chris Wilson Signed-off-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index da24825acc8..9534e72fdbc 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3740,16 +3740,21 @@ void gen6_update_ring_freq(struct drm_device *dev) unsigned int gpu_freq; unsigned int max_ia_freq, min_ring_freq; int scaling_factor = 180; + struct cpufreq_policy *policy; WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); - max_ia_freq = cpufreq_quick_get_max(0); - /* - * Default to measured freq if none found, PCU will ensure we don't go - * over - */ - if (!max_ia_freq) + policy = cpufreq_cpu_get(0); + if (policy) { + max_ia_freq = policy->cpuinfo.max_freq; + cpufreq_cpu_put(policy); + } else { + /* + * Default to measured freq if none found, PCU will ensure we + * don't go over + */ max_ia_freq = tsc_khz; + } /* Convert from kHz to MHz */ max_ia_freq /= 1000; -- cgit v1.2.3-70-g09d2 From 4c445e0ebc648ee42c0d21713b8f76597854d47a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2013 17:24:58 +0300 Subject: drm/i915: Rename primary_disabled to primary_enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's try to avoid these confusing negated booleans. Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 10 +++++----- drivers/gpu/drm/i915/intel_drv.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 2 +- drivers/gpu/drm/i915/intel_sprite.c | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b54a4cf899f..ebe5d0840a8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1840,9 +1840,9 @@ static void intel_enable_primary_plane(struct drm_i915_private *dev_priv, /* If the pipe isn't enabled, we can't pump pixels and may hang */ assert_pipe_enabled(dev_priv, pipe); - WARN(!intel_crtc->primary_disabled, "Primary plane already enabled\n"); + WARN(intel_crtc->primary_enabled, "Primary plane already enabled\n"); - intel_crtc->primary_disabled = false; + intel_crtc->primary_enabled = true; reg = DSPCNTR(plane); val = I915_READ(reg); @@ -1870,9 +1870,9 @@ static void intel_disable_primary_plane(struct drm_i915_private *dev_priv, int reg; u32 val; - WARN(intel_crtc->primary_disabled, "Primary plane already disabled\n"); + WARN(!intel_crtc->primary_enabled, "Primary plane already disabled\n"); - intel_crtc->primary_disabled = true; + intel_crtc->primary_enabled = false; reg = DSPCNTR(plane); val = I915_READ(reg); @@ -10706,7 +10706,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) &crtc->config); crtc->base.enabled = crtc->active; - crtc->primary_disabled = !crtc->active; + crtc->primary_enabled = crtc->active; DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n", crtc->base.base.id, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index ce80289de69..b497a96af08 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -321,7 +321,7 @@ struct intel_crtc { */ bool active; bool eld_vld; - bool primary_disabled; /* is the crtc obscured by a plane? */ + bool primary_enabled; /* is the primary plane (partially) visible? */ bool lowfreq_avail; struct intel_overlay *overlay; struct intel_unpin_work *unpin_work; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9534e72fdbc..c91087a542e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -475,7 +475,7 @@ void intel_update_fbc(struct drm_device *dev) */ list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { if (intel_crtc_active(tmp_crtc) && - !to_intel_crtc(tmp_crtc)->primary_disabled) { + to_intel_crtc(tmp_crtc)->primary_enabled) { if (crtc) { if (set_no_fbc_reason(dev_priv, FBC_MULTIPLE_PIPES)) DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index e001d2c35c3..8afaad6bcc4 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -521,10 +521,10 @@ intel_enable_primary(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int reg = DSPCNTR(intel_crtc->plane); - if (!intel_crtc->primary_disabled) + if (intel_crtc->primary_enabled) return; - intel_crtc->primary_disabled = false; + intel_crtc->primary_enabled = true; I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE); intel_flush_primary_plane(dev_priv, intel_crtc->plane); @@ -553,10 +553,10 @@ intel_disable_primary(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int reg = DSPCNTR(intel_crtc->plane); - if (intel_crtc->primary_disabled) + if (!intel_crtc->primary_enabled) return; - intel_crtc->primary_disabled = true; + intel_crtc->primary_enabled = false; mutex_lock(&dev->struct_mutex); if (dev_priv->fbc.plane == intel_crtc->plane) -- cgit v1.2.3-70-g09d2 From c0951f0c97bc1528262a92b193fed7942cc6c54c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 10 Oct 2013 21:58:50 +0100 Subject: drm/i915: Avoid tweaking RPS before it is enabled As we delay the initial RPS enabling (upon boot and after resume), there is a chance that we may start to render and trigger RPS boosts before we set up the punit. Any changes we make could result in inconsistent hardware state, with a danger of causing undefined behaviour. However, as the boosting is a optional tweak to RPS, we can simply ignore it whilst RPS is not yet enabled. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: Jesse Barnes Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 26 ++++++++++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9cac93c41e1..36b82cc48b4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -862,6 +862,7 @@ struct intel_gen6_power_mgmt { int last_adj; enum { LOW_POWER, BETWEEN, HIGH_POWER } power; + bool enabled; struct delayed_work delayed_resume_work; /* diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index c91087a542e..ca3dd566974 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3442,22 +3442,26 @@ void gen6_set_rps(struct drm_device *dev, u8 val) void gen6_rps_idle(struct drm_i915_private *dev_priv) { mutex_lock(&dev_priv->rps.hw_lock); - if (dev_priv->info->is_valleyview) - valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_delay); - else - gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay); - dev_priv->rps.last_adj = 0; + if (dev_priv->rps.enabled) { + if (dev_priv->info->is_valleyview) + valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_delay); + else + gen6_set_rps(dev_priv->dev, dev_priv->rps.min_delay); + dev_priv->rps.last_adj = 0; + } mutex_unlock(&dev_priv->rps.hw_lock); } void gen6_rps_boost(struct drm_i915_private *dev_priv) { mutex_lock(&dev_priv->rps.hw_lock); - if (dev_priv->info->is_valleyview) - valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_delay); - else - gen6_set_rps(dev_priv->dev, dev_priv->rps.max_delay); - dev_priv->rps.last_adj = 0; + if (dev_priv->rps.enabled) { + if (dev_priv->info->is_valleyview) + valleyview_set_rps(dev_priv->dev, dev_priv->rps.max_delay); + else + gen6_set_rps(dev_priv->dev, dev_priv->rps.max_delay); + dev_priv->rps.last_adj = 0; + } mutex_unlock(&dev_priv->rps.hw_lock); } @@ -4716,6 +4720,7 @@ void intel_disable_gt_powersave(struct drm_device *dev) valleyview_disable_rps(dev); else gen6_disable_rps(dev); + dev_priv->rps.enabled = false; mutex_unlock(&dev_priv->rps.hw_lock); } } @@ -4735,6 +4740,7 @@ static void intel_gen6_powersave_work(struct work_struct *work) gen6_enable_rps(dev); gen6_update_ring_freq(dev); } + dev_priv->rps.enabled = true; mutex_unlock(&dev_priv->rps.hw_lock); } -- cgit v1.2.3-70-g09d2 From 0b2ae6d72e445b58ae39cfa6ec0b8d3f53ff7a6f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2013 19:17:55 +0300 Subject: drm/i915: Add intel_pipe_wm and prepare for watermark pre-compute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce a new struct intel_pipe_wm which contains all the watermarks for a single pipe. Use it to unify the LP0 and LP1+ watermark computations so that we can just iterate through the watermark levels neatly and call ilk_compute_wm_level() for each. Also add another tool ilk_wm_merge() that merges the LP1+ watermarks from all pipes. For that, embed one intel_pipe_wm inside intel_crtc that contains the currently valid watermarks for each pipe. This is mainly preparatory work for pre-computing the watermarks for each pipe and merging them at a later time. For now the merging still happens immediately. v2: Add some comments about level 0 DDB split and intel_wm_config Add WARN_ON for level 0 being disabled s/lp_wm/merged Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_drv.h | 12 +++ drivers/gpu/drm/i915/intel_pm.c | 192 +++++++++++++++++++++++---------------- 2 files changed, 128 insertions(+), 76 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 189257df7a0..5d5d34911a7 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -309,6 +309,12 @@ struct intel_crtc_config { bool double_wide; }; +struct intel_pipe_wm { + struct intel_wm_level wm[5]; + uint32_t linetime; + bool fbc_wm_enabled; +}; + struct intel_crtc { struct drm_crtc base; enum pipe pipe; @@ -349,6 +355,12 @@ struct intel_crtc { /* Access to these should be protected by dev_priv->irq_lock. */ bool cpu_fifo_underrun_disabled; bool pch_fifo_underrun_disabled; + + /* per-pipe watermark state */ + struct { + /* watermarks currently being used */ + struct intel_pipe_wm active; + } wm; }; struct intel_plane_wm_parameters { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ca3dd566974..3e1b50359af 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2458,53 +2458,6 @@ static void ilk_compute_wm_level(struct drm_i915_private *dev_priv, result->enable = true; } -static bool hsw_compute_lp_wm(struct drm_i915_private *dev_priv, - int level, const struct hsw_wm_maximums *max, - const struct hsw_pipe_wm_parameters *params, - struct intel_wm_level *result) -{ - enum pipe pipe; - struct intel_wm_level res[3]; - - for (pipe = PIPE_A; pipe <= PIPE_C; pipe++) - ilk_compute_wm_level(dev_priv, level, ¶ms[pipe], &res[pipe]); - - result->pri_val = max3(res[0].pri_val, res[1].pri_val, res[2].pri_val); - result->spr_val = max3(res[0].spr_val, res[1].spr_val, res[2].spr_val); - result->cur_val = max3(res[0].cur_val, res[1].cur_val, res[2].cur_val); - result->fbc_val = max3(res[0].fbc_val, res[1].fbc_val, res[2].fbc_val); - result->enable = true; - - return ilk_check_wm(level, max, result); -} - - -static uint32_t hsw_compute_wm_pipe(struct drm_device *dev, - const struct hsw_pipe_wm_parameters *params) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_wm_config config = { - .num_pipes_active = 1, - .sprites_enabled = params->spr.enabled, - .sprites_scaled = params->spr.scaled, - }; - struct hsw_wm_maximums max; - struct intel_wm_level res; - - if (!params->active) - return 0; - - ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max); - - ilk_compute_wm_level(dev_priv, 0, params, &res); - - ilk_check_wm(0, &max, &res); - - return (res.pri_val << WM0_PIPE_PLANE_SHIFT) | - (res.spr_val << WM0_PIPE_SPRITE_SHIFT) | - res.cur_val; -} - static uint32_t hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc) { @@ -2687,44 +2640,123 @@ static void hsw_compute_wm_parameters(struct drm_device *dev, *lp_max_5_6 = *lp_max_1_2; } +/* Compute new watermarks for the pipe */ +static bool intel_compute_pipe_wm(struct drm_crtc *crtc, + const struct hsw_pipe_wm_parameters *params, + struct intel_pipe_wm *pipe_wm) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int level, max_level = ilk_wm_max_level(dev); + /* LP0 watermark maximums depend on this pipe alone */ + struct intel_wm_config config = { + .num_pipes_active = 1, + .sprites_enabled = params->spr.enabled, + .sprites_scaled = params->spr.scaled, + }; + struct hsw_wm_maximums max; + + memset(pipe_wm, 0, sizeof(*pipe_wm)); + + /* LP0 watermarks always use 1/2 DDB partitioning */ + ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max); + + for (level = 0; level <= max_level; level++) + ilk_compute_wm_level(dev_priv, level, params, + &pipe_wm->wm[level]); + + pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc); + + /* At least LP0 must be valid */ + return ilk_check_wm(0, &max, &pipe_wm->wm[0]); +} + +/* + * Merge the watermarks from all active pipes for a specific level. + */ +static void ilk_merge_wm_level(struct drm_device *dev, + int level, + struct intel_wm_level *ret_wm) +{ + const struct intel_crtc *intel_crtc; + + list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) { + const struct intel_wm_level *wm = + &intel_crtc->wm.active.wm[level]; + + if (!wm->enable) + return; + + ret_wm->pri_val = max(ret_wm->pri_val, wm->pri_val); + ret_wm->spr_val = max(ret_wm->spr_val, wm->spr_val); + ret_wm->cur_val = max(ret_wm->cur_val, wm->cur_val); + ret_wm->fbc_val = max(ret_wm->fbc_val, wm->fbc_val); + } + + ret_wm->enable = true; +} + +/* + * Merge all low power watermarks for all active pipes. + */ +static void ilk_wm_merge(struct drm_device *dev, + const struct hsw_wm_maximums *max, + struct intel_pipe_wm *merged) +{ + int level, max_level = ilk_wm_max_level(dev); + + merged->fbc_wm_enabled = true; + + /* merge each WM1+ level */ + for (level = 1; level <= max_level; level++) { + struct intel_wm_level *wm = &merged->wm[level]; + + ilk_merge_wm_level(dev, level, wm); + + if (!ilk_check_wm(level, max, wm)) + break; + + /* + * The spec says it is preferred to disable + * FBC WMs instead of disabling a WM level. + */ + if (wm->fbc_val > max->fbc) { + merged->fbc_wm_enabled = false; + wm->fbc_val = 0; + } + } +} + static void hsw_compute_wm_results(struct drm_device *dev, const struct hsw_pipe_wm_parameters *params, const struct hsw_wm_maximums *lp_maximums, struct hsw_wm_values *results) { - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc; - struct intel_wm_level lp_results[4] = {}; - enum pipe pipe; - int level, max_level, wm_lp; + struct intel_crtc *intel_crtc; + int level, wm_lp; + struct intel_pipe_wm merged = {}; - for (level = 1; level <= 4; level++) - if (!hsw_compute_lp_wm(dev_priv, level, - lp_maximums, params, - &lp_results[level - 1])) - break; - max_level = level - 1; + list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) + intel_compute_pipe_wm(&intel_crtc->base, + ¶ms[intel_crtc->pipe], + &intel_crtc->wm.active); + + ilk_wm_merge(dev, lp_maximums, &merged); memset(results, 0, sizeof(*results)); - /* The spec says it is preferred to disable FBC WMs instead of disabling - * a WM level. */ - results->enable_fbc_wm = true; - for (level = 1; level <= max_level; level++) { - if (lp_results[level - 1].fbc_val > lp_maximums->fbc) { - results->enable_fbc_wm = false; - lp_results[level - 1].fbc_val = 0; - } - } + results->enable_fbc_wm = merged.fbc_wm_enabled; + /* LP1+ register values */ for (wm_lp = 1; wm_lp <= 3; wm_lp++) { const struct intel_wm_level *r; - level = (max_level == 4 && wm_lp > 1) ? wm_lp + 1 : wm_lp; - if (level > max_level) + level = wm_lp + (wm_lp >= 2 && merged.wm[4].enable); + + r = &merged.wm[level]; + if (!r->enable) break; - r = &lp_results[level - 1]; results->wm_lp[wm_lp - 1] = HSW_WM_LP_VAL(level * 2, r->fbc_val, r->pri_val, @@ -2732,13 +2764,21 @@ static void hsw_compute_wm_results(struct drm_device *dev, results->wm_lp_spr[wm_lp - 1] = r->spr_val; } - for_each_pipe(pipe) - results->wm_pipe[pipe] = hsw_compute_wm_pipe(dev, - ¶ms[pipe]); + /* LP0 register values */ + list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) { + enum pipe pipe = intel_crtc->pipe; + const struct intel_wm_level *r = + &intel_crtc->wm.active.wm[0]; - for_each_pipe(pipe) { - crtc = dev_priv->pipe_to_crtc_mapping[pipe]; - results->wm_linetime[pipe] = hsw_compute_linetime_wm(dev, crtc); + if (WARN_ON(!r->enable)) + continue; + + results->wm_linetime[pipe] = intel_crtc->wm.active.linetime; + + results->wm_pipe[pipe] = + (r->pri_val << WM0_PIPE_PLANE_SHIFT) | + (r->spr_val << WM0_PIPE_SPRITE_SHIFT) | + r->cur_val; } } -- cgit v1.2.3-70-g09d2 From 7c4a395ff8f441acb7876281c6777624e6410349 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2013 19:17:56 +0300 Subject: drm/i915: Don't re-compute pipe watermarks except for the affected pipe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No point in re-computing the watermarks for all pipes, when only one pipe has changed. The watermarks stored under intel_crtc.wm.active are still valid for the other pipes. We just need to redo the merging. We can also skip the merge/update procedure completely if the new watermarks for the affected pipe come out unchanged. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 67 +++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 39 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3e1b50359af..3699f1d574c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2584,29 +2584,19 @@ static void intel_setup_wm_latency(struct drm_device *dev) intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency); } -static void hsw_compute_wm_parameters(struct drm_device *dev, - struct hsw_pipe_wm_parameters *params, +static void hsw_compute_wm_parameters(struct drm_crtc *crtc, + struct hsw_pipe_wm_parameters *p, struct hsw_wm_maximums *lp_max_1_2, struct hsw_wm_maximums *lp_max_5_6) { - struct drm_crtc *crtc; - struct drm_plane *plane; - enum pipe pipe; + struct drm_device *dev = crtc->dev; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + enum pipe pipe = intel_crtc->pipe; struct intel_wm_config config = {}; + struct drm_plane *plane; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct hsw_pipe_wm_parameters *p; - - pipe = intel_crtc->pipe; - p = ¶ms[pipe]; - - p->active = intel_crtc_active(crtc); - if (!p->active) - continue; - - config.num_pipes_active++; - + p->active = intel_crtc_active(crtc); + if (p->active) { p->pipe_htotal = intel_crtc->config.adjusted_mode.htotal; p->pixel_rate = ilk_pipe_pixel_rate(dev, crtc); p->pri.bytes_per_pixel = crtc->fb->bits_per_pixel / 8; @@ -2618,17 +2608,17 @@ static void hsw_compute_wm_parameters(struct drm_device *dev, p->cur.enabled = true; } + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + config.num_pipes_active += intel_crtc_active(crtc); + list_for_each_entry(plane, &dev->mode_config.plane_list, head) { struct intel_plane *intel_plane = to_intel_plane(plane); - struct hsw_pipe_wm_parameters *p; - - pipe = intel_plane->pipe; - p = ¶ms[pipe]; - p->spr = intel_plane->wm; + if (intel_plane->pipe == pipe) + p->spr = intel_plane->wm; - config.sprites_enabled |= p->spr.enabled; - config.sprites_scaled |= p->spr.scaled; + config.sprites_enabled |= intel_plane->wm.enabled; + config.sprites_scaled |= intel_plane->wm.scaled; } ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2); @@ -2656,8 +2646,6 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc, }; struct hsw_wm_maximums max; - memset(pipe_wm, 0, sizeof(*pipe_wm)); - /* LP0 watermarks always use 1/2 DDB partitioning */ ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max); @@ -2728,7 +2716,6 @@ static void ilk_wm_merge(struct drm_device *dev, } static void hsw_compute_wm_results(struct drm_device *dev, - const struct hsw_pipe_wm_parameters *params, const struct hsw_wm_maximums *lp_maximums, struct hsw_wm_values *results) { @@ -2736,11 +2723,6 @@ static void hsw_compute_wm_results(struct drm_device *dev, int level, wm_lp; struct intel_pipe_wm merged = {}; - list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head) - intel_compute_pipe_wm(&intel_crtc->base, - ¶ms[intel_crtc->pipe], - &intel_crtc->wm.active); - ilk_wm_merge(dev, lp_maximums, &merged); memset(results, 0, sizeof(*results)); @@ -2907,20 +2889,27 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, static void haswell_update_wm(struct drm_crtc *crtc) { + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct hsw_wm_maximums lp_max_1_2, lp_max_5_6; - struct hsw_pipe_wm_parameters params[3]; + struct hsw_pipe_wm_parameters params = {}; struct hsw_wm_values results_1_2, results_5_6, *best_results; enum intel_ddb_partitioning partitioning; + struct intel_pipe_wm pipe_wm = {}; + + hsw_compute_wm_parameters(crtc, ¶ms, &lp_max_1_2, &lp_max_5_6); + + intel_compute_pipe_wm(crtc, ¶ms, &pipe_wm); + + if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm))) + return; - hsw_compute_wm_parameters(dev, params, &lp_max_1_2, &lp_max_5_6); + intel_crtc->wm.active = pipe_wm; - hsw_compute_wm_results(dev, params, - &lp_max_1_2, &results_1_2); + hsw_compute_wm_results(dev, &lp_max_1_2, &results_1_2); if (lp_max_1_2.pri != lp_max_5_6.pri) { - hsw_compute_wm_results(dev, params, - &lp_max_5_6, &results_5_6); + hsw_compute_wm_results(dev, &lp_max_5_6, &results_5_6); best_results = hsw_find_best_result(&results_1_2, &results_5_6); } else { best_results = &results_1_2; -- cgit v1.2.3-70-g09d2 From 0362c7816c8ad5d838ecd93f5526c1c725a1a8fd Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2013 19:17:57 +0300 Subject: drm/i915: Move LP1+ watermark merging out from hsw_compute_wm_results() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I want to convert hsw_find_best_result() to use intel_pipe_wm, so we need to move the merging to happen outside hsw_compute_wm_results(). Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3699f1d574c..71524ae0f07 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2716,26 +2716,23 @@ static void ilk_wm_merge(struct drm_device *dev, } static void hsw_compute_wm_results(struct drm_device *dev, - const struct hsw_wm_maximums *lp_maximums, + const struct intel_pipe_wm *merged, struct hsw_wm_values *results) { struct intel_crtc *intel_crtc; int level, wm_lp; - struct intel_pipe_wm merged = {}; - - ilk_wm_merge(dev, lp_maximums, &merged); memset(results, 0, sizeof(*results)); - results->enable_fbc_wm = merged.fbc_wm_enabled; + results->enable_fbc_wm = merged->fbc_wm_enabled; /* LP1+ register values */ for (wm_lp = 1; wm_lp <= 3; wm_lp++) { const struct intel_wm_level *r; - level = wm_lp + (wm_lp >= 2 && merged.wm[4].enable); + level = wm_lp + (wm_lp >= 2 && merged->wm[4].enable); - r = &merged.wm[level]; + r = &merged->wm[level]; if (!r->enable) break; @@ -2897,6 +2894,7 @@ static void haswell_update_wm(struct drm_crtc *crtc) struct hsw_wm_values results_1_2, results_5_6, *best_results; enum intel_ddb_partitioning partitioning; struct intel_pipe_wm pipe_wm = {}; + struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}; hsw_compute_wm_parameters(crtc, ¶ms, &lp_max_1_2, &lp_max_5_6); @@ -2907,9 +2905,12 @@ static void haswell_update_wm(struct drm_crtc *crtc) intel_crtc->wm.active = pipe_wm; - hsw_compute_wm_results(dev, &lp_max_1_2, &results_1_2); + ilk_wm_merge(dev, &lp_max_1_2, &lp_wm_1_2); + ilk_wm_merge(dev, &lp_max_5_6, &lp_wm_5_6); + + hsw_compute_wm_results(dev, &lp_wm_1_2, &results_1_2); if (lp_max_1_2.pri != lp_max_5_6.pri) { - hsw_compute_wm_results(dev, &lp_max_5_6, &results_5_6); + hsw_compute_wm_results(dev, &lp_wm_5_6, &results_5_6); best_results = hsw_find_best_result(&results_1_2, &results_5_6); } else { best_results = &results_1_2; -- cgit v1.2.3-70-g09d2 From 198a1e9b1822099f60945a6c46b1f59727347817 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2013 19:17:58 +0300 Subject: drm/i915: Use intel_pipe_wm in hsw_find_best_results MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's try to keep using the intermediate intel_pipe_wm representation for as long as possible. It avoids subtle knowledge about the internals of the hardware registers when trying to choose the best watermark configuration. While at it replace the memset() w/ zero initialization. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 71524ae0f07..91147722ee7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2722,8 +2722,6 @@ static void hsw_compute_wm_results(struct drm_device *dev, struct intel_crtc *intel_crtc; int level, wm_lp; - memset(results, 0, sizeof(*results)); - results->enable_fbc_wm = merged->fbc_wm_enabled; /* LP1+ register values */ @@ -2763,24 +2761,26 @@ static void hsw_compute_wm_results(struct drm_device *dev, /* Find the result with the highest level enabled. Check for enable_fbc_wm in * case both are at the same level. Prefer r1 in case they're the same. */ -static struct hsw_wm_values *hsw_find_best_result(struct hsw_wm_values *r1, - struct hsw_wm_values *r2) +static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev, + struct intel_pipe_wm *r1, + struct intel_pipe_wm *r2) { - int i, val_r1 = 0, val_r2 = 0; + int level, max_level = ilk_wm_max_level(dev); + int level1 = 0, level2 = 0; - for (i = 0; i < 3; i++) { - if (r1->wm_lp[i] & WM3_LP_EN) - val_r1 = r1->wm_lp[i] & WM1_LP_LATENCY_MASK; - if (r2->wm_lp[i] & WM3_LP_EN) - val_r2 = r2->wm_lp[i] & WM1_LP_LATENCY_MASK; + for (level = 1; level <= max_level; level++) { + if (r1->wm[level].enable) + level1 = level; + if (r2->wm[level].enable) + level2 = level; } - if (val_r1 == val_r2) { - if (r2->enable_fbc_wm && !r1->enable_fbc_wm) + if (level1 == level2) { + if (r2->fbc_wm_enabled && !r1->fbc_wm_enabled) return r2; else return r1; - } else if (val_r1 > val_r2) { + } else if (level1 > level2) { return r1; } else { return r2; @@ -2891,10 +2891,10 @@ static void haswell_update_wm(struct drm_crtc *crtc) struct drm_i915_private *dev_priv = dev->dev_private; struct hsw_wm_maximums lp_max_1_2, lp_max_5_6; struct hsw_pipe_wm_parameters params = {}; - struct hsw_wm_values results_1_2, results_5_6, *best_results; + struct hsw_wm_values results = {}; enum intel_ddb_partitioning partitioning; struct intel_pipe_wm pipe_wm = {}; - struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}; + struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm; hsw_compute_wm_parameters(crtc, ¶ms, &lp_max_1_2, &lp_max_5_6); @@ -2908,18 +2908,18 @@ static void haswell_update_wm(struct drm_crtc *crtc) ilk_wm_merge(dev, &lp_max_1_2, &lp_wm_1_2); ilk_wm_merge(dev, &lp_max_5_6, &lp_wm_5_6); - hsw_compute_wm_results(dev, &lp_wm_1_2, &results_1_2); if (lp_max_1_2.pri != lp_max_5_6.pri) { - hsw_compute_wm_results(dev, &lp_wm_5_6, &results_5_6); - best_results = hsw_find_best_result(&results_1_2, &results_5_6); + best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6); } else { - best_results = &results_1_2; + best_lp_wm = &lp_wm_1_2; } - partitioning = (best_results == &results_1_2) ? + hsw_compute_wm_results(dev, best_lp_wm, &results); + + partitioning = (best_lp_wm == &lp_wm_1_2) ? INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6; - hsw_write_wm_values(dev_priv, best_results, partitioning); + hsw_write_wm_values(dev_priv, &results, partitioning); } static void haswell_update_sprite_wm(struct drm_plane *plane, -- cgit v1.2.3-70-g09d2 From a485bfb8d0d70ba24662aab5e00b2914c646220b Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2013 19:17:59 +0300 Subject: drm/i915: Move some computations out from hsw_compute_wm_parameters() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the watermark max computations into haswell_update_wm(). This allows keeping the 1/2 vs. 5/6 split code in one place, and avoid having to pass around so many things. We also save a bit of stack space by only requiring one copy of struct hsw_wm_maximums. Also move the intel_wm_config out from hsw_compute_wm_parameters() and pass it it. We'll have some need for it in haswell_update_wm() later. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 91147722ee7..3d3f1134f16 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2586,13 +2586,11 @@ static void intel_setup_wm_latency(struct drm_device *dev) static void hsw_compute_wm_parameters(struct drm_crtc *crtc, struct hsw_pipe_wm_parameters *p, - struct hsw_wm_maximums *lp_max_1_2, - struct hsw_wm_maximums *lp_max_5_6) + struct intel_wm_config *config) { struct drm_device *dev = crtc->dev; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum pipe pipe = intel_crtc->pipe; - struct intel_wm_config config = {}; struct drm_plane *plane; p->active = intel_crtc_active(crtc); @@ -2609,7 +2607,7 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc, } list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - config.num_pipes_active += intel_crtc_active(crtc); + config->num_pipes_active += intel_crtc_active(crtc); list_for_each_entry(plane, &dev->mode_config.plane_list, head) { struct intel_plane *intel_plane = to_intel_plane(plane); @@ -2617,17 +2615,9 @@ static void hsw_compute_wm_parameters(struct drm_crtc *crtc, if (intel_plane->pipe == pipe) p->spr = intel_plane->wm; - config.sprites_enabled |= intel_plane->wm.enabled; - config.sprites_scaled |= intel_plane->wm.scaled; + config->sprites_enabled |= intel_plane->wm.enabled; + config->sprites_scaled |= intel_plane->wm.scaled; } - - ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, lp_max_1_2); - - /* 5/6 split only in single pipe config on IVB+ */ - if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1) - ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, lp_max_5_6); - else - *lp_max_5_6 = *lp_max_1_2; } /* Compute new watermarks for the pipe */ @@ -2889,14 +2879,15 @@ static void haswell_update_wm(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct hsw_wm_maximums lp_max_1_2, lp_max_5_6; + struct hsw_wm_maximums max; struct hsw_pipe_wm_parameters params = {}; struct hsw_wm_values results = {}; enum intel_ddb_partitioning partitioning; struct intel_pipe_wm pipe_wm = {}; struct intel_pipe_wm lp_wm_1_2 = {}, lp_wm_5_6 = {}, *best_lp_wm; + struct intel_wm_config config = {}; - hsw_compute_wm_parameters(crtc, ¶ms, &lp_max_1_2, &lp_max_5_6); + hsw_compute_wm_parameters(crtc, ¶ms, &config); intel_compute_pipe_wm(crtc, ¶ms, &pipe_wm); @@ -2905,10 +2896,14 @@ static void haswell_update_wm(struct drm_crtc *crtc) intel_crtc->wm.active = pipe_wm; - ilk_wm_merge(dev, &lp_max_1_2, &lp_wm_1_2); - ilk_wm_merge(dev, &lp_max_5_6, &lp_wm_5_6); + ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, &max); + ilk_wm_merge(dev, &max, &lp_wm_1_2); + + /* 5/6 split only in single pipe config on IVB+ */ + if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1) { + ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &max); + ilk_wm_merge(dev, &max, &lp_wm_5_6); - if (lp_max_1_2.pri != lp_max_5_6.pri) { best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6); } else { best_lp_wm = &lp_wm_1_2; -- cgit v1.2.3-70-g09d2 From a5db6b62577b14a9fbe639af0aba9ec7ae85ae3e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 11 Oct 2013 15:26:26 +0300 Subject: drm/i915: Check 5/6 DDB split only when sprites are enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the 5/6 DDB split make sense only when sprites are enabled. So check that before we waste any cycles computing the merged watermarks with the 5/6 DDB split. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 3d3f1134f16..a5503cd7a1c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2900,7 +2900,7 @@ static void haswell_update_wm(struct drm_crtc *crtc) ilk_wm_merge(dev, &max, &lp_wm_1_2); /* 5/6 split only in single pipe config on IVB+ */ - if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active <= 1) { + if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active == 1) { ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &max); ilk_wm_merge(dev, &max, &lp_wm_5_6); -- cgit v1.2.3-70-g09d2 From b380ca3caa821150fddab0052dcce624d18e88ee Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2013 19:18:01 +0300 Subject: drm/i915: Refactor wm_lp to level calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On HSW the LP1,LP2,LP3 levels are either 1,2,3 or 1,3,4. We make the conversion from LPn to to the level at one point current. Later we're going to do it in a few places, so move it to a separate function. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a5503cd7a1c..9f33e37f8a2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2705,6 +2705,12 @@ static void ilk_wm_merge(struct drm_device *dev, } } +static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm) +{ + /* LP1,LP2,LP3 levels are either 1,2,3 or 1,3,4 */ + return wm_lp + (wm_lp >= 2 && pipe_wm->wm[4].enable); +} + static void hsw_compute_wm_results(struct drm_device *dev, const struct intel_pipe_wm *merged, struct hsw_wm_values *results) @@ -2718,7 +2724,7 @@ static void hsw_compute_wm_results(struct drm_device *dev, for (wm_lp = 1; wm_lp <= 3; wm_lp++) { const struct intel_wm_level *r; - level = wm_lp + (wm_lp >= 2 && merged->wm[4].enable); + level = ilk_wm_lp_to_level(wm_lp, merged); r = &merged->wm[level]; if (!r->enable) -- cgit v1.2.3-70-g09d2 From 7eaa4d56107dac87946f3b45faf37bc831f8de83 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2013 19:18:02 +0300 Subject: drm/i915: Kill fbc_wm_enabled from intel_wm_config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fbc_wm_enabled member in intel_wm_config is useless for the time being. The original idea for it was that we'd pre-compute it and so that the WM merging process could know whether it needs to worry about FBC watermarks at all. But we don't have a convenient way to pre-check for the possibility of FBC being used. intel_update_fbc() should be split up for that. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9f33e37f8a2..abea03c1e48 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2213,7 +2213,6 @@ struct intel_wm_config { unsigned int num_pipes_active; bool sprites_enabled; bool sprites_scaled; - bool fbc_wm_enabled; }; /* -- cgit v1.2.3-70-g09d2 From 609cedef6a9d5d90574903c71e81bd1c1f311f06 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2013 19:18:03 +0300 Subject: drm/i915: Store current watermark state in dev_priv->wm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To make it easier to check what watermark updates are actually necessary, keep copies of the relevant bits that match the current hardware state. Also add DDB partitioning into hsw_wm_values as that's another piece of state we want to track. We don't read out the hardware state on init yet, so we can't really start using this yet, but it will be used later. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni [danvet: Paulo asked for a comment around the memcmp to say that we depend upon zero-initializing the entire structures due to padding. But a later patch in this series removes the memcmp again. So this is ok as-is.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 12 +++++++++++ drivers/gpu/drm/i915/intel_pm.c | 46 ++++++++++++++--------------------------- 2 files changed, 27 insertions(+), 31 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2ea66f23c2b..6106d3d710c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1141,6 +1141,15 @@ struct intel_wm_level { uint32_t fbc_val; }; +struct hsw_wm_values { + uint32_t wm_pipe[3]; + uint32_t wm_lp[3]; + uint32_t wm_lp_spr[3]; + uint32_t wm_linetime[3]; + bool enable_fbc_wm; + enum intel_ddb_partitioning partitioning; +}; + /* * This struct tracks the state needed for the Package C8+ feature. * @@ -1402,6 +1411,9 @@ typedef struct drm_i915_private { uint16_t spr_latency[5]; /* cursor */ uint16_t cur_latency[5]; + + /* current hardware state */ + struct hsw_wm_values hw; } wm; struct i915_package_c8 pc8; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index abea03c1e48..6d3d5f62dd6 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2200,14 +2200,6 @@ struct hsw_wm_maximums { uint16_t fbc; }; -struct hsw_wm_values { - uint32_t wm_pipe[3]; - uint32_t wm_lp[3]; - uint32_t wm_lp_spr[3]; - uint32_t wm_linetime[3]; - bool enable_fbc_wm; -}; - /* used in computing the new watermarks state */ struct intel_wm_config { unsigned int num_pipes_active; @@ -2712,12 +2704,14 @@ static int ilk_wm_lp_to_level(int wm_lp, const struct intel_pipe_wm *pipe_wm) static void hsw_compute_wm_results(struct drm_device *dev, const struct intel_pipe_wm *merged, + enum intel_ddb_partitioning partitioning, struct hsw_wm_values *results) { struct intel_crtc *intel_crtc; int level, wm_lp; results->enable_fbc_wm = merged->fbc_wm_enabled; + results->partitioning = partitioning; /* LP1+ register values */ for (wm_lp = 1; wm_lp <= 3; wm_lp++) { @@ -2787,13 +2781,10 @@ static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev, * causes WMs to be re-evaluated, expending some power. */ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, - struct hsw_wm_values *results, - enum intel_ddb_partitioning partitioning) + struct hsw_wm_values *results) { struct hsw_wm_values previous; uint32_t val; - enum intel_ddb_partitioning prev_partitioning; - bool prev_enable_fbc_wm; previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK); previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK); @@ -2808,21 +2799,12 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B)); previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C)); - prev_partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ? + previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ? INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; - prev_enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS); - - if (memcmp(results->wm_pipe, previous.wm_pipe, - sizeof(results->wm_pipe)) == 0 && - memcmp(results->wm_lp, previous.wm_lp, - sizeof(results->wm_lp)) == 0 && - memcmp(results->wm_lp_spr, previous.wm_lp_spr, - sizeof(results->wm_lp_spr)) == 0 && - memcmp(results->wm_linetime, previous.wm_linetime, - sizeof(results->wm_linetime)) == 0 && - partitioning == prev_partitioning && - results->enable_fbc_wm == prev_enable_fbc_wm) + previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS); + + if (memcmp(results, &previous, sizeof(*results)) == 0) return; if (previous.wm_lp[2] != 0) @@ -2846,16 +2828,16 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, if (previous.wm_linetime[2] != results->wm_linetime[2]) I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]); - if (prev_partitioning != partitioning) { + if (previous.partitioning != results->partitioning) { val = I915_READ(WM_MISC); - if (partitioning == INTEL_DDB_PART_1_2) + if (results->partitioning == INTEL_DDB_PART_1_2) val &= ~WM_MISC_DATA_PARTITION_5_6; else val |= WM_MISC_DATA_PARTITION_5_6; I915_WRITE(WM_MISC, val); } - if (prev_enable_fbc_wm != results->enable_fbc_wm) { + if (previous.enable_fbc_wm != results->enable_fbc_wm) { val = I915_READ(DISP_ARB_CTL); if (results->enable_fbc_wm) val &= ~DISP_FBC_WM_DIS; @@ -2877,6 +2859,8 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, I915_WRITE(WM2_LP_ILK, results->wm_lp[1]); if (results->wm_lp[2] != 0) I915_WRITE(WM3_LP_ILK, results->wm_lp[2]); + + dev_priv->wm.hw = *results; } static void haswell_update_wm(struct drm_crtc *crtc) @@ -2914,12 +2898,12 @@ static void haswell_update_wm(struct drm_crtc *crtc) best_lp_wm = &lp_wm_1_2; } - hsw_compute_wm_results(dev, best_lp_wm, &results); - partitioning = (best_lp_wm == &lp_wm_1_2) ? INTEL_DDB_PART_1_2 : INTEL_DDB_PART_5_6; - hsw_write_wm_values(dev_priv, &results, partitioning); + hsw_compute_wm_results(dev, best_lp_wm, partitioning, &results); + + hsw_write_wm_values(dev_priv, &results); } static void haswell_update_sprite_wm(struct drm_plane *plane, -- cgit v1.2.3-70-g09d2 From 49a687c471396d063bb3d3cf04d62568efe7ec5e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 11 Oct 2013 19:39:52 +0300 Subject: drm/i915: Improve watermark dirtyness checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently hsw_write_vm_values() may write to certain watermark registers needlessly. For instance if only, say, LP3 changes, the current code will again disable all LP1+ watermarks even though only LP3 needs to be reconfigured. Add an easy to read function that will compute the dirtyness of the watermarks, and use that information to further optimize the watermark programming. v2: Disable LP1+ watermarks around changing LP0 watermarks for Paulo Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 98 +++++++++++++++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6d3d5f62dd6..6d0c3d0e80f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2776,6 +2776,66 @@ static struct intel_pipe_wm *hsw_find_best_result(struct drm_device *dev, } } +/* dirty bits used to track which watermarks need changes */ +#define WM_DIRTY_PIPE(pipe) (1 << (pipe)) +#define WM_DIRTY_LINETIME(pipe) (1 << (8 + (pipe))) +#define WM_DIRTY_LP(wm_lp) (1 << (15 + (wm_lp))) +#define WM_DIRTY_LP_ALL (WM_DIRTY_LP(1) | WM_DIRTY_LP(2) | WM_DIRTY_LP(3)) +#define WM_DIRTY_FBC (1 << 24) +#define WM_DIRTY_DDB (1 << 25) + +static unsigned int ilk_compute_wm_dirty(struct drm_device *dev, + const struct hsw_wm_values *old, + const struct hsw_wm_values *new) +{ + unsigned int dirty = 0; + enum pipe pipe; + int wm_lp; + + for_each_pipe(pipe) { + if (old->wm_linetime[pipe] != new->wm_linetime[pipe]) { + dirty |= WM_DIRTY_LINETIME(pipe); + /* Must disable LP1+ watermarks too */ + dirty |= WM_DIRTY_LP_ALL; + } + + if (old->wm_pipe[pipe] != new->wm_pipe[pipe]) { + dirty |= WM_DIRTY_PIPE(pipe); + /* Must disable LP1+ watermarks too */ + dirty |= WM_DIRTY_LP_ALL; + } + } + + if (old->enable_fbc_wm != new->enable_fbc_wm) { + dirty |= WM_DIRTY_FBC; + /* Must disable LP1+ watermarks too */ + dirty |= WM_DIRTY_LP_ALL; + } + + if (old->partitioning != new->partitioning) { + dirty |= WM_DIRTY_DDB; + /* Must disable LP1+ watermarks too */ + dirty |= WM_DIRTY_LP_ALL; + } + + /* LP1+ watermarks already deemed dirty, no need to continue */ + if (dirty & WM_DIRTY_LP_ALL) + return dirty; + + /* Find the lowest numbered LP1+ watermark in need of an update... */ + for (wm_lp = 1; wm_lp <= 3; wm_lp++) { + if (old->wm_lp[wm_lp - 1] != new->wm_lp[wm_lp - 1] || + old->wm_lp_spr[wm_lp - 1] != new->wm_lp_spr[wm_lp - 1]) + break; + } + + /* ...and mark it and all higher numbered LP1+ watermarks as dirty */ + for (; wm_lp <= 3; wm_lp++) + dirty |= WM_DIRTY_LP(wm_lp); + + return dirty; +} + /* * The spec says we shouldn't write when we don't need, because every write * causes WMs to be re-evaluated, expending some power. @@ -2784,6 +2844,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, struct hsw_wm_values *results) { struct hsw_wm_values previous; + unsigned int dirty; uint32_t val; previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK); @@ -2804,31 +2865,32 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS); - if (memcmp(results, &previous, sizeof(*results)) == 0) + dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results); + if (!dirty) return; - if (previous.wm_lp[2] != 0) + if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0) I915_WRITE(WM3_LP_ILK, 0); - if (previous.wm_lp[1] != 0) + if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0) I915_WRITE(WM2_LP_ILK, 0); - if (previous.wm_lp[0] != 0) + if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0) I915_WRITE(WM1_LP_ILK, 0); - if (previous.wm_pipe[0] != results->wm_pipe[0]) + if (dirty & WM_DIRTY_PIPE(PIPE_A)) I915_WRITE(WM0_PIPEA_ILK, results->wm_pipe[0]); - if (previous.wm_pipe[1] != results->wm_pipe[1]) + if (dirty & WM_DIRTY_PIPE(PIPE_B)) I915_WRITE(WM0_PIPEB_ILK, results->wm_pipe[1]); - if (previous.wm_pipe[2] != results->wm_pipe[2]) + if (dirty & WM_DIRTY_PIPE(PIPE_C)) I915_WRITE(WM0_PIPEC_IVB, results->wm_pipe[2]); - if (previous.wm_linetime[0] != results->wm_linetime[0]) + if (dirty & WM_DIRTY_LINETIME(PIPE_A)) I915_WRITE(PIPE_WM_LINETIME(PIPE_A), results->wm_linetime[0]); - if (previous.wm_linetime[1] != results->wm_linetime[1]) + if (dirty & WM_DIRTY_LINETIME(PIPE_B)) I915_WRITE(PIPE_WM_LINETIME(PIPE_B), results->wm_linetime[1]); - if (previous.wm_linetime[2] != results->wm_linetime[2]) + if (dirty & WM_DIRTY_LINETIME(PIPE_C)) I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]); - if (previous.partitioning != results->partitioning) { + if (dirty & WM_DIRTY_DDB) { val = I915_READ(WM_MISC); if (results->partitioning == INTEL_DDB_PART_1_2) val &= ~WM_MISC_DATA_PARTITION_5_6; @@ -2837,7 +2899,7 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, I915_WRITE(WM_MISC, val); } - if (previous.enable_fbc_wm != results->enable_fbc_wm) { + if (dirty & WM_DIRTY_FBC) { val = I915_READ(DISP_ARB_CTL); if (results->enable_fbc_wm) val &= ~DISP_FBC_WM_DIS; @@ -2846,18 +2908,18 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, I915_WRITE(DISP_ARB_CTL, val); } - if (previous.wm_lp_spr[0] != results->wm_lp_spr[0]) + if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0]) I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]); - if (previous.wm_lp_spr[1] != results->wm_lp_spr[1]) + if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1]) I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]); - if (previous.wm_lp_spr[2] != results->wm_lp_spr[2]) + if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2]) I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]); - if (results->wm_lp[0] != 0) + if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0) I915_WRITE(WM1_LP_ILK, results->wm_lp[0]); - if (results->wm_lp[1] != 0) + if (dirty & WM_DIRTY_LP(2) && results->wm_lp[1] != 0) I915_WRITE(WM2_LP_ILK, results->wm_lp[1]); - if (results->wm_lp[2] != 0) + if (dirty & WM_DIRTY_LP(3) && results->wm_lp[2] != 0) I915_WRITE(WM3_LP_ILK, results->wm_lp[2]); dev_priv->wm.hw = *results; -- cgit v1.2.3-70-g09d2 From 243e6a44b9ca5aa3c9ce47459a53e03b1dc7e665 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 14 Oct 2013 14:55:24 +0300 Subject: drm/i915: Init HSW watermark tracking in intel_modeset_setup_hw_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fill out the HSW watermark s/w tracking structures with the current hardware state in intel_modeset_setup_hw_state(). This allows us to skip the HW state readback during watermark programming and just use the values we keep around in dev_priv->wm. Reduces the overhead of the watermark programming quite a bit. v2: s/init_wm/wm_get_hw_state Remove stale comment about sprites Make DDB partitioning readout safer Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni [danvet: Fix whitespace fail.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 3 ++ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 102 ++++++++++++++++++++++++++--------- 3 files changed, 80 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e6a4ca16f33..53ad5cb9e80 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10839,6 +10839,9 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, pll->on = false; } + if (IS_HASWELL(dev)) + ilk_wm_get_hw_state(dev); + if (force_restore) { i915_redisable_vga(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5d5d34911a7..e33f387d418 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -839,6 +839,7 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv); void gen6_rps_boost(struct drm_i915_private *dev_priv); void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv); void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv); +void ilk_wm_get_hw_state(struct drm_device *dev); /* intel_sdvo.c */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6d0c3d0e80f..77ee14fa007 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2843,37 +2843,19 @@ static unsigned int ilk_compute_wm_dirty(struct drm_device *dev, static void hsw_write_wm_values(struct drm_i915_private *dev_priv, struct hsw_wm_values *results) { - struct hsw_wm_values previous; + struct hsw_wm_values *previous = &dev_priv->wm.hw; unsigned int dirty; uint32_t val; - previous.wm_pipe[0] = I915_READ(WM0_PIPEA_ILK); - previous.wm_pipe[1] = I915_READ(WM0_PIPEB_ILK); - previous.wm_pipe[2] = I915_READ(WM0_PIPEC_IVB); - previous.wm_lp[0] = I915_READ(WM1_LP_ILK); - previous.wm_lp[1] = I915_READ(WM2_LP_ILK); - previous.wm_lp[2] = I915_READ(WM3_LP_ILK); - previous.wm_lp_spr[0] = I915_READ(WM1S_LP_ILK); - previous.wm_lp_spr[1] = I915_READ(WM2S_LP_IVB); - previous.wm_lp_spr[2] = I915_READ(WM3S_LP_IVB); - previous.wm_linetime[0] = I915_READ(PIPE_WM_LINETIME(PIPE_A)); - previous.wm_linetime[1] = I915_READ(PIPE_WM_LINETIME(PIPE_B)); - previous.wm_linetime[2] = I915_READ(PIPE_WM_LINETIME(PIPE_C)); - - previous.partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ? - INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; - - previous.enable_fbc_wm = !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS); - - dirty = ilk_compute_wm_dirty(dev_priv->dev, &previous, results); + dirty = ilk_compute_wm_dirty(dev_priv->dev, previous, results); if (!dirty) return; - if (dirty & WM_DIRTY_LP(3) && previous.wm_lp[2] != 0) + if (dirty & WM_DIRTY_LP(3) && previous->wm_lp[2] != 0) I915_WRITE(WM3_LP_ILK, 0); - if (dirty & WM_DIRTY_LP(2) && previous.wm_lp[1] != 0) + if (dirty & WM_DIRTY_LP(2) && previous->wm_lp[1] != 0) I915_WRITE(WM2_LP_ILK, 0); - if (dirty & WM_DIRTY_LP(1) && previous.wm_lp[0] != 0) + if (dirty & WM_DIRTY_LP(1) && previous->wm_lp[0] != 0) I915_WRITE(WM1_LP_ILK, 0); if (dirty & WM_DIRTY_PIPE(PIPE_A)) @@ -2908,11 +2890,11 @@ static void hsw_write_wm_values(struct drm_i915_private *dev_priv, I915_WRITE(DISP_ARB_CTL, val); } - if (dirty & WM_DIRTY_LP(1) && previous.wm_lp_spr[0] != results->wm_lp_spr[0]) + if (dirty & WM_DIRTY_LP(1) && previous->wm_lp_spr[0] != results->wm_lp_spr[0]) I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]); - if (dirty & WM_DIRTY_LP(2) && previous.wm_lp_spr[1] != results->wm_lp_spr[1]) + if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1]) I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]); - if (dirty & WM_DIRTY_LP(3) && previous.wm_lp_spr[2] != results->wm_lp_spr[2]) + if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2]) I915_WRITE(WM3S_LP_IVB, results->wm_lp_spr[2]); if (dirty & WM_DIRTY_LP(1) && results->wm_lp[0] != 0) @@ -3145,6 +3127,74 @@ static void sandybridge_update_sprite_wm(struct drm_plane *plane, I915_WRITE(WM3S_LP_IVB, sprite_wm); } +static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct hsw_wm_values *hw = &dev_priv->wm.hw; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_pipe_wm *active = &intel_crtc->wm.active; + enum pipe pipe = intel_crtc->pipe; + static const unsigned int wm0_pipe_reg[] = { + [PIPE_A] = WM0_PIPEA_ILK, + [PIPE_B] = WM0_PIPEB_ILK, + [PIPE_C] = WM0_PIPEC_IVB, + }; + + hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]); + hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe)); + + if (intel_crtc_active(crtc)) { + u32 tmp = hw->wm_pipe[pipe]; + + /* + * For active pipes LP0 watermark is marked as + * enabled, and LP1+ watermaks as disabled since + * we can't really reverse compute them in case + * multiple pipes are active. + */ + active->wm[0].enable = true; + active->wm[0].pri_val = (tmp & WM0_PIPE_PLANE_MASK) >> WM0_PIPE_PLANE_SHIFT; + active->wm[0].spr_val = (tmp & WM0_PIPE_SPRITE_MASK) >> WM0_PIPE_SPRITE_SHIFT; + active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK; + active->linetime = hw->wm_linetime[pipe]; + } else { + int level, max_level = ilk_wm_max_level(dev); + + /* + * For inactive pipes, all watermark levels + * should be marked as enabled but zeroed, + * which is what we'd compute them to. + */ + for (level = 0; level <= max_level; level++) + active->wm[level].enable = true; + } +} + +void ilk_wm_get_hw_state(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct hsw_wm_values *hw = &dev_priv->wm.hw; + struct drm_crtc *crtc; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + ilk_pipe_wm_get_hw_state(crtc); + + hw->wm_lp[0] = I915_READ(WM1_LP_ILK); + hw->wm_lp[1] = I915_READ(WM2_LP_ILK); + hw->wm_lp[2] = I915_READ(WM3_LP_ILK); + + hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK); + hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB); + hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB); + + hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ? + INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; + + hw->enable_fbc_wm = + !(I915_READ(DISP_ARB_CTL) & DISP_FBC_WM_DIS); +} + /** * intel_update_watermarks - update FIFO watermark values based on current modes * -- cgit v1.2.3-70-g09d2 From dcaf13f7924b86b201f163fd71aad31a5a64fd71 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2013 19:18:06 +0300 Subject: drm/i915: Remove a somewhat silly debug print from watermark code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This debug print just adds overhead to the watermark merging process, and doesn't really give enough information to be useful. Just kill and let's add something much better a bit later. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 77ee14fa007..63b3f5e4b25 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2421,8 +2421,6 @@ static bool ilk_check_wm(int level, result->enable = true; } - DRM_DEBUG_KMS("WM%d: %sabled\n", level, result->enable ? "en" : "dis"); - return ret; } -- cgit v1.2.3-70-g09d2 From 34982fe1303b7e4f24fb8a0a238ebffc8135af84 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2013 19:18:09 +0300 Subject: drm/i915: Rename ilk_wm_max to ilk_compute_wm_maximums MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makes the intention more clear. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 63b3f5e4b25..493a3133415 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2371,11 +2371,11 @@ static unsigned int ilk_fbc_wm_max(void) return 15; } -static void ilk_wm_max(struct drm_device *dev, - int level, - const struct intel_wm_config *config, - enum intel_ddb_partitioning ddb_partitioning, - struct hsw_wm_maximums *max) +static void ilk_compute_wm_maximums(struct drm_device *dev, + int level, + const struct intel_wm_config *config, + enum intel_ddb_partitioning ddb_partitioning, + struct hsw_wm_maximums *max) { max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false); max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true); @@ -2626,7 +2626,7 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc, struct hsw_wm_maximums max; /* LP0 watermarks always use 1/2 DDB partitioning */ - ilk_wm_max(dev, 0, &config, INTEL_DDB_PART_1_2, &max); + ilk_compute_wm_maximums(dev, 0, &config, INTEL_DDB_PART_1_2, &max); for (level = 0; level <= max_level; level++) ilk_compute_wm_level(dev_priv, level, params, @@ -2927,12 +2927,12 @@ static void haswell_update_wm(struct drm_crtc *crtc) intel_crtc->wm.active = pipe_wm; - ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_1_2, &max); + ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_1_2, &max); ilk_wm_merge(dev, &max, &lp_wm_1_2); /* 5/6 split only in single pipe config on IVB+ */ if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active == 1) { - ilk_wm_max(dev, 1, &config, INTEL_DDB_PART_5_6, &max); + ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max); ilk_wm_merge(dev, &max, &lp_wm_5_6); best_lp_wm = hsw_find_best_result(dev, &lp_wm_1_2, &lp_wm_5_6); -- cgit v1.2.3-70-g09d2 From d9395655b92bc80c33cb6fbacbefb9ebf16403d4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 9 Oct 2013 19:18:10 +0300 Subject: drm/i915: Rename ilk_check_wm to ilk_validate_wm_level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Makes the behaviour of the function more clear. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 493a3133415..cdd78f69a28 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2383,9 +2383,9 @@ static void ilk_compute_wm_maximums(struct drm_device *dev, max->fbc = ilk_fbc_wm_max(); } -static bool ilk_check_wm(int level, - const struct hsw_wm_maximums *max, - struct intel_wm_level *result) +static bool ilk_validate_wm_level(int level, + const struct hsw_wm_maximums *max, + struct intel_wm_level *result) { bool ret; @@ -2635,7 +2635,7 @@ static bool intel_compute_pipe_wm(struct drm_crtc *crtc, pipe_wm->linetime = hsw_compute_linetime_wm(dev, crtc); /* At least LP0 must be valid */ - return ilk_check_wm(0, &max, &pipe_wm->wm[0]); + return ilk_validate_wm_level(0, &max, &pipe_wm->wm[0]); } /* @@ -2680,7 +2680,7 @@ static void ilk_wm_merge(struct drm_device *dev, ilk_merge_wm_level(dev, level, wm); - if (!ilk_check_wm(level, max, wm)) + if (!ilk_validate_wm_level(level, max, wm)) break; /* -- cgit v1.2.3-70-g09d2 From ec98c8d1ffdc87c54ec0896db45db5b7bd22eca9 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 11 Oct 2013 15:26:26 +0300 Subject: drm/i915: Check 5/6 DDB split only when sprites are enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the 5/6 DDB split make sense only when sprites are enabled. So check that before we waste any cycles computing the merged watermarks with the 5/6 DDB split. Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cdd78f69a28..8064ff927bc 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2931,7 +2931,8 @@ static void haswell_update_wm(struct drm_crtc *crtc) ilk_wm_merge(dev, &max, &lp_wm_1_2); /* 5/6 split only in single pipe config on IVB+ */ - if (INTEL_INFO(dev)->gen >= 7 && config.num_pipes_active == 1) { + if (INTEL_INFO(dev)->gen >= 7 && + config.num_pipes_active == 1 && config.sprites_enabled) { ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max); ilk_wm_merge(dev, &max, &lp_wm_5_6); -- cgit v1.2.3-70-g09d2 From dc39fff7229c01550cad1ee8fa0309dfafdcd2e7 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 18 Oct 2013 12:32:07 -0700 Subject: drm/i915: Print RC6 info less often Since we use intel_enable_rc6() now for more than just when we're enabling RC6, we'll see this message many times, and it is just confusing. As an example, calc_residency calls this function whenever poked via sysfs. This leaves the impression in dmesg that we're constantly re-enabling RC6. While at it, move the defines and description from drv.h to intel_pm.c, since these are only ever used in that code. Signed-off-by: Ben Widawsky Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 21 ---------------- drivers/gpu/drm/i915/intel_pm.c | 54 ++++++++++++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 32 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2ea33eebf01..dee03325d59 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1784,27 +1784,6 @@ struct drm_i915_file_private { #include "i915_trace.h" -/** - * RC6 is a special power stage which allows the GPU to enter an very - * low-voltage mode when idle, using down to 0V while at this stage. This - * stage is entered automatically when the GPU is idle when RC6 support is - * enabled, and as soon as new workload arises GPU wakes up automatically as well. - * - * There are different RC6 modes available in Intel GPU, which differentiate - * among each other with the latency required to enter and leave RC6 and - * voltage consumed by the GPU in different states. - * - * The combination of the following flags define which states GPU is allowed - * to enter, while RC6 is the normal RC6 state, RC6p is the deep RC6, and - * RC6pp is deepest RC6. Their support by hardware varies according to the - * GPU, BIOS, chipset and platform. RC6 is usually the safest one and the one - * which brings the most power savings; deeper states save more power, but - * require higher latency to switch to and wake up. - */ -#define INTEL_RC6_ENABLE (1<<0) -#define INTEL_RC6p_ENABLE (1<<1) -#define INTEL_RC6pp_ENABLE (1<<2) - extern const struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; extern unsigned int i915_fbpercrtc __always_unused; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8064ff927bc..bff5fa37703 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -32,6 +32,27 @@ #include #include +/** + * RC6 is a special power stage which allows the GPU to enter an very + * low-voltage mode when idle, using down to 0V while at this stage. This + * stage is entered automatically when the GPU is idle when RC6 support is + * enabled, and as soon as new workload arises GPU wakes up automatically as well. + * + * There are different RC6 modes available in Intel GPU, which differentiate + * among each other with the latency required to enter and leave RC6 and + * voltage consumed by the GPU in different states. + * + * The combination of the following flags define which states GPU is allowed + * to enter, while RC6 is the normal RC6 state, RC6p is the deep RC6, and + * RC6pp is deepest RC6. Their support by hardware varies according to the + * GPU, BIOS, chipset and platform. RC6 is usually the safest one and the one + * which brings the most power savings; deeper states save more power, but + * require higher latency to switch to and wake up. + */ +#define INTEL_RC6_ENABLE (1<<0) +#define INTEL_RC6p_ENABLE (1<<1) +#define INTEL_RC6pp_ENABLE (1<<2) + /* FBC, or Frame Buffer Compression, is a technique employed to compress the * framebuffer contents in-memory, aiming at reducing the required bandwidth * during in-memory transfers and, therefore, reduce the power packet. @@ -3685,6 +3706,20 @@ static void valleyview_disable_rps(struct drm_device *dev) } } +static void intel_print_rc6_info(struct drm_device *dev, u32 mode) +{ + if (IS_GEN6(dev)) + DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); + + if (IS_HASWELL(dev)) + DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); + + DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", + (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", + (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", + (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); +} + int intel_enable_rc6(const struct drm_device *dev) { /* No RC6 before Ironlake */ @@ -3699,18 +3734,13 @@ int intel_enable_rc6(const struct drm_device *dev) if (INTEL_INFO(dev)->gen == 5) return 0; - if (IS_HASWELL(dev)) { - DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); + if (IS_HASWELL(dev)) return INTEL_RC6_ENABLE; - } /* snb/ivb have more than one rc6 state. */ - if (INTEL_INFO(dev)->gen == 6) { - DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); + if (INTEL_INFO(dev)->gen == 6) return INTEL_RC6_ENABLE; - } - DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n"); return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); } @@ -3812,10 +3842,7 @@ static void gen6_enable_rps(struct drm_device *dev) rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; } - DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", - (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", - (rc6_mask & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", - (rc6_mask & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); + intel_print_rc6_info(dev, rc6_mask); I915_WRITE(GEN6_RC_CONTROL, rc6_mask | @@ -4051,6 +4078,9 @@ static void valleyview_enable_rps(struct drm_device *dev) VLV_RENDER_RC6_COUNT_EN)); if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) rc6_mode = GEN7_RC_CTL_TO_MODE; + + intel_print_rc6_info(dev, rc6_mode); + I915_WRITE(GEN6_RC_CONTROL, rc6_mode); val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); @@ -4222,6 +4252,8 @@ static void ironlake_enable_rc6(struct drm_device *dev) I915_WRITE(PWRCTXA, i915_gem_obj_ggtt_offset(dev_priv->ips.pwrctx) | PWRCTX_EN); I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); + + intel_print_rc6_info(dev, INTEL_RC6_ENABLE); } static unsigned long intel_pxfreq(u32 vidfreq) -- cgit v1.2.3-70-g09d2 From bddc76452d16cd1101ba29c0cff653cb8313b010 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Oct 2013 17:25:49 +0300 Subject: drm/i915: factor out is_always_on_domain It is just cleaner this way and makes it easier to add support for other HW generations with always-on power wells powering a different set of domains. Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 8 ++++ drivers/gpu/drm/i915/intel_pm.c | 84 +++++++++++++++-------------------------- 2 files changed, 38 insertions(+), 54 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 87857d781dd..f3a930d3ade 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -100,8 +100,12 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_C, POWER_DOMAIN_TRANSCODER_EDP, POWER_DOMAIN_VGA, + + POWER_DOMAIN_NUM, }; +#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1) + #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A) #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \ ((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER) @@ -109,6 +113,10 @@ enum intel_display_power_domain { ((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \ (tran) + POWER_DOMAIN_TRANSCODER_A) +#define HSW_ALWAYS_ON_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_PIPE_A) | \ + BIT(POWER_DOMAIN_TRANSCODER_EDP)) + enum hpd_pin { HPD_NONE = 0, HPD_PORT_A = HPD_NONE, /* PORT_A is internal */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index bff5fa37703..97abb33e8c9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5517,6 +5517,23 @@ void intel_suspend_hw(struct drm_device *dev) lpt_suspend_hw(dev); } +static bool is_always_on_power_domain(struct drm_device *dev, + enum intel_display_power_domain domain) +{ + unsigned long always_on_domains; + + BUG_ON(BIT(domain) & ~POWER_DOMAIN_MASK); + + if (IS_HASWELL(dev)) { + always_on_domains = HSW_ALWAYS_ON_POWER_DOMAINS; + } else { + WARN_ON(1); + return true; + } + + return BIT(domain) & always_on_domains; +} + /** * We should only use the power well if we explicitly asked the hardware to * enable it, so check if it's enabled and also check if we've requested it to @@ -5530,24 +5547,11 @@ bool intel_display_power_enabled(struct drm_device *dev, if (!HAS_POWER_WELL(dev)) return true; - switch (domain) { - case POWER_DOMAIN_PIPE_A: - case POWER_DOMAIN_TRANSCODER_EDP: + if (is_always_on_power_domain(dev, domain)) return true; - case POWER_DOMAIN_VGA: - case POWER_DOMAIN_PIPE_B: - case POWER_DOMAIN_PIPE_C: - case POWER_DOMAIN_PIPE_A_PANEL_FITTER: - case POWER_DOMAIN_PIPE_B_PANEL_FITTER: - case POWER_DOMAIN_PIPE_C_PANEL_FITTER: - case POWER_DOMAIN_TRANSCODER_A: - case POWER_DOMAIN_TRANSCODER_B: - case POWER_DOMAIN_TRANSCODER_C: - return I915_READ(HSW_PWR_WELL_DRIVER) == + + return I915_READ(HSW_PWR_WELL_DRIVER) == (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); - default: - BUG(); - } } static void __intel_set_power_well(struct drm_device *dev, bool enable) @@ -5619,26 +5623,12 @@ void intel_display_power_get(struct drm_device *dev, if (!HAS_POWER_WELL(dev)) return; - switch (domain) { - case POWER_DOMAIN_PIPE_A: - case POWER_DOMAIN_TRANSCODER_EDP: + if (is_always_on_power_domain(dev, domain)) return; - case POWER_DOMAIN_VGA: - case POWER_DOMAIN_PIPE_B: - case POWER_DOMAIN_PIPE_C: - case POWER_DOMAIN_PIPE_A_PANEL_FITTER: - case POWER_DOMAIN_PIPE_B_PANEL_FITTER: - case POWER_DOMAIN_PIPE_C_PANEL_FITTER: - case POWER_DOMAIN_TRANSCODER_A: - case POWER_DOMAIN_TRANSCODER_B: - case POWER_DOMAIN_TRANSCODER_C: - spin_lock_irq(&power_well->lock); - __intel_power_well_get(power_well); - spin_unlock_irq(&power_well->lock); - return; - default: - BUG(); - } + + spin_lock_irq(&power_well->lock); + __intel_power_well_get(power_well); + spin_unlock_irq(&power_well->lock); } void intel_display_power_put(struct drm_device *dev, @@ -5650,26 +5640,12 @@ void intel_display_power_put(struct drm_device *dev, if (!HAS_POWER_WELL(dev)) return; - switch (domain) { - case POWER_DOMAIN_PIPE_A: - case POWER_DOMAIN_TRANSCODER_EDP: + if (is_always_on_power_domain(dev, domain)) return; - case POWER_DOMAIN_VGA: - case POWER_DOMAIN_PIPE_B: - case POWER_DOMAIN_PIPE_C: - case POWER_DOMAIN_PIPE_A_PANEL_FITTER: - case POWER_DOMAIN_PIPE_B_PANEL_FITTER: - case POWER_DOMAIN_PIPE_C_PANEL_FITTER: - case POWER_DOMAIN_TRANSCODER_A: - case POWER_DOMAIN_TRANSCODER_B: - case POWER_DOMAIN_TRANSCODER_C: - spin_lock_irq(&power_well->lock); - __intel_power_well_put(power_well); - spin_unlock_irq(&power_well->lock); - return; - default: - BUG(); - } + + spin_lock_irq(&power_well->lock); + __intel_power_well_put(power_well); + spin_unlock_irq(&power_well->lock); } static struct i915_power_well *hsw_pwr; -- cgit v1.2.3-70-g09d2 From 959cbc1b8a2534bb930d237ee164893a4936a4d6 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Oct 2013 17:25:50 +0300 Subject: drm/i915: change power_well->lock to be mutex There is no hard need for this to be a spin lock, as we don't take these locks in irq context from anywhere. An upcoming patch will add calls to punit read/write functions from within regions protected by this lock and those functions need a mutex in turn. As a solution for that convert the spin lock to be a mutex. Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f3a930d3ade..faface98ba3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -909,7 +909,7 @@ struct intel_ilk_power_mgmt { /* Power well structure for haswell */ struct i915_power_well { struct drm_device *device; - spinlock_t lock; + struct mutex lock; /* power well enable/disable usage count */ int count; int i915_request; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 97abb33e8c9..f3136659877 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5626,9 +5626,9 @@ void intel_display_power_get(struct drm_device *dev, if (is_always_on_power_domain(dev, domain)) return; - spin_lock_irq(&power_well->lock); + mutex_lock(&power_well->lock); __intel_power_well_get(power_well); - spin_unlock_irq(&power_well->lock); + mutex_unlock(&power_well->lock); } void intel_display_power_put(struct drm_device *dev, @@ -5643,9 +5643,9 @@ void intel_display_power_put(struct drm_device *dev, if (is_always_on_power_domain(dev, domain)) return; - spin_lock_irq(&power_well->lock); + mutex_lock(&power_well->lock); __intel_power_well_put(power_well); - spin_unlock_irq(&power_well->lock); + mutex_unlock(&power_well->lock); } static struct i915_power_well *hsw_pwr; @@ -5656,9 +5656,9 @@ void i915_request_power_well(void) if (WARN_ON(!hsw_pwr)) return; - spin_lock_irq(&hsw_pwr->lock); + mutex_lock(&hsw_pwr->lock); __intel_power_well_get(hsw_pwr); - spin_unlock_irq(&hsw_pwr->lock); + mutex_unlock(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_request_power_well); @@ -5668,9 +5668,9 @@ void i915_release_power_well(void) if (WARN_ON(!hsw_pwr)) return; - spin_lock_irq(&hsw_pwr->lock); + mutex_lock(&hsw_pwr->lock); __intel_power_well_put(hsw_pwr); - spin_unlock_irq(&hsw_pwr->lock); + mutex_unlock(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_release_power_well); @@ -5681,7 +5681,7 @@ int i915_init_power_well(struct drm_device *dev) hsw_pwr = &dev_priv->power_well; hsw_pwr->device = dev; - spin_lock_init(&hsw_pwr->lock); + mutex_init(&hsw_pwr->lock); hsw_pwr->count = 0; return 0; @@ -5703,7 +5703,7 @@ void intel_set_power_well(struct drm_device *dev, bool enable) if (!i915_disable_power_well && !enable) return; - spin_lock_irq(&power_well->lock); + mutex_lock(&power_well->lock); /* * This function will only ever contribute one @@ -5722,7 +5722,7 @@ void intel_set_power_well(struct drm_device *dev, bool enable) __intel_power_well_put(power_well); out: - spin_unlock_irq(&power_well->lock); + mutex_unlock(&power_well->lock); } static void intel_resume_power_well(struct drm_device *dev) @@ -5733,9 +5733,9 @@ static void intel_resume_power_well(struct drm_device *dev) if (!HAS_POWER_WELL(dev)) return; - spin_lock_irq(&power_well->lock); + mutex_lock(&power_well->lock); __intel_set_power_well(dev, power_well->count > 0); - spin_unlock_irq(&power_well->lock); + mutex_unlock(&power_well->lock); } /* -- cgit v1.2.3-70-g09d2 From 153b4b9547965729120d427485e414855399acac Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 22 Oct 2013 22:05:09 -0700 Subject: drm/i915: Convert straggling MCHBAR registers All our registers which are written through the MCHBAR are defined descriptively as an offset to the MCHBAR. We had 3 outliers here. Convert these as well so all registers which are offsets are MCHBAR can be easily identified/found within the code. With this, convert DCLK to also follow this format. Signed-off-by: Ben Widawsky Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 8 ++++---- drivers/gpu/drm/i915/intel_pm.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d1fb06a6a3f..e4fef047a06 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1476,7 +1476,7 @@ #define MCHBAR_MIRROR_BASE_SNB 0x140000 /* Memory controller frequency in MCHBAR for Haswell (possible SNB+) */ -#define DCLK 0x5e04 +#define DCLK (MCHBAR_MIRROR_BASE_SNB + 0x5e04) /** 915-945 and GM965 MCH register controlling DRAM channel access */ #define DCC 0x10200 @@ -1771,9 +1771,9 @@ #define GEN6_GT_THREAD_STATUS_CORE_MASK 0x7 #define GEN6_GT_THREAD_STATUS_CORE_MASK_HSW (0x7 | (0x07 << 16)) -#define GEN6_GT_PERF_STATUS 0x145948 -#define GEN6_RP_STATE_LIMITS 0x145994 -#define GEN6_RP_STATE_CAP 0x145998 +#define GEN6_GT_PERF_STATUS (MCHBAR_MIRROR_BASE_SNB + 0x5948) +#define GEN6_RP_STATE_LIMITS (MCHBAR_MIRROR_BASE_SNB + 0x5994) +#define GEN6_RP_STATE_CAP (MCHBAR_MIRROR_BASE_SNB + 0x5998) /* * Logical Context regs diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f3136659877..2f26d6c2fc9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3915,7 +3915,7 @@ void gen6_update_ring_freq(struct drm_device *dev) /* Convert from kHz to MHz */ max_ia_freq /= 1000; - min_ring_freq = I915_READ(MCHBAR_MIRROR_BASE_SNB + DCLK) & 0xf; + min_ring_freq = I915_READ(DCLK) & 0xf; /* convert DDR frequency from units of 266.6MHz to bandwidth */ min_ring_freq = mult_frac(min_ring_freq, 8, 3); -- cgit v1.2.3-70-g09d2 From a74b0c481589762f28f35a26b2c77126f38de652 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 24 Oct 2013 09:59:11 -0700 Subject: drm/i915: Remove WaFbcDisableDpfcClockGating on IVB Production IVB does not need it. I confirmed this with Art. Signed-off-by: Ben Widawsky Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2f26d6c2fc9..c325a57b89b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -254,12 +254,6 @@ static void ironlake_disable_fbc(struct drm_device *dev) dpfc_ctl &= ~DPFC_CTL_EN; I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); - if (IS_IVYBRIDGE(dev)) - /* WaFbcDisableDpfcClockGating:ivb */ - I915_WRITE(ILK_DSPCLK_GATE_D, - I915_READ(ILK_DSPCLK_GATE_D) & - ~ILK_DPFCUNIT_CLOCK_GATE_DISABLE); - if (IS_HASWELL(dev)) /* WaFbcDisableDpfcClockGating:hsw */ I915_WRITE(HSW_CLKGATE_DISABLE_PART_1, @@ -295,10 +289,6 @@ static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval) if (IS_IVYBRIDGE(dev)) { /* WaFbcAsynchFlipDisableFbcQueue:ivb */ I915_WRITE(ILK_DISPLAY_CHICKEN1, ILK_FBCQ_DIS); - /* WaFbcDisableDpfcClockGating:ivb */ - I915_WRITE(ILK_DSPCLK_GATE_D, - I915_READ(ILK_DSPCLK_GATE_D) | - ILK_DPFCUNIT_CLOCK_GATE_DISABLE); } else { /* WaFbcAsynchFlipDisableFbcQueue:hsw */ I915_WRITE(HSW_PIPE_SLICE_CHICKEN_1(intel_crtc->pipe), -- cgit v1.2.3-70-g09d2 From 8c7b72f20b5d197bf70e93e87046def20eaa3f36 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 24 Oct 2013 09:59:12 -0700 Subject: drm/i915: Remove WaFbcDisableDpfcClockGating on HSW Production HSW does not need it. I confirmed this with Art. Signed-off-by: Ben Widawsky Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 --- drivers/gpu/drm/i915/intel_pm.c | 10 ---------- 2 files changed, 13 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e4fef047a06..47de41f1d4b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1106,9 +1106,6 @@ _HSW_PIPE_SLICE_CHICKEN_1_A, + \ _HSW_PIPE_SLICE_CHICKEN_1_B) -#define HSW_CLKGATE_DISABLE_PART_1 0x46500 -#define HSW_DPFC_GATING_DISABLE (1<<23) - /* * GPIO regs */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index c325a57b89b..03b5a01c2d5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -254,12 +254,6 @@ static void ironlake_disable_fbc(struct drm_device *dev) dpfc_ctl &= ~DPFC_CTL_EN; I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); - if (IS_HASWELL(dev)) - /* WaFbcDisableDpfcClockGating:hsw */ - I915_WRITE(HSW_CLKGATE_DISABLE_PART_1, - I915_READ(HSW_CLKGATE_DISABLE_PART_1) & - ~HSW_DPFC_GATING_DISABLE); - DRM_DEBUG_KMS("disabled FBC\n"); } } @@ -293,10 +287,6 @@ static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval) /* WaFbcAsynchFlipDisableFbcQueue:hsw */ I915_WRITE(HSW_PIPE_SLICE_CHICKEN_1(intel_crtc->pipe), HSW_BYPASS_FBC_QUEUE); - /* WaFbcDisableDpfcClockGating:hsw */ - I915_WRITE(HSW_CLKGATE_DISABLE_PART_1, - I915_READ(HSW_CLKGATE_DISABLE_PART_1) | - HSW_DPFC_GATING_DISABLE); } I915_WRITE(SNB_DPFC_CTL_SA, -- cgit v1.2.3-70-g09d2 From 83c00f55302219fdac1f8628e61f2b63cffc58d5 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 25 Oct 2013 17:36:47 +0300 Subject: drm/i915: prepare for multiple power wells In the future we'll need to support multiple power wells, so prepare for that here. Create a new power domains struct which contains all power domain/well specific fields. Since we'll have one lock protecting all power wells, move power_well->lock to the new struct too. No functional change. Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 11 ++++++--- drivers/gpu/drm/i915/intel_pm.c | 55 +++++++++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 24 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5bfcf0f91a5..8371182f748 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -909,12 +909,18 @@ struct intel_ilk_power_mgmt { /* Power well structure for haswell */ struct i915_power_well { struct drm_device *device; - struct mutex lock; /* power well enable/disable usage count */ int count; int i915_request; }; +#define I915_MAX_POWER_WELLS 1 + +struct i915_power_domains { + struct mutex lock; + struct i915_power_well power_wells[I915_MAX_POWER_WELLS]; +}; + struct i915_dri1_state { unsigned allow_batchbuffer : 1; u32 __iomem *gfx_hws_cpu_addr; @@ -1410,8 +1416,7 @@ typedef struct drm_i915_private { * mchdev_lock in intel_pm.c */ struct intel_ilk_power_mgmt ips; - /* Haswell power well */ - struct i915_power_well power_well; + struct i915_power_domains power_domains; struct i915_psr psr; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 03b5a01c2d5..5869482f3f6 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5598,7 +5598,7 @@ void intel_display_power_get(struct drm_device *dev, enum intel_display_power_domain domain) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_well *power_well = &dev_priv->power_well; + struct i915_power_domains *power_domains; if (!HAS_POWER_WELL(dev)) return; @@ -5606,16 +5606,18 @@ void intel_display_power_get(struct drm_device *dev, if (is_always_on_power_domain(dev, domain)) return; - mutex_lock(&power_well->lock); - __intel_power_well_get(power_well); - mutex_unlock(&power_well->lock); + power_domains = &dev_priv->power_domains; + + mutex_lock(&power_domains->lock); + __intel_power_well_get(&power_domains->power_wells[0]); + mutex_unlock(&power_domains->lock); } void intel_display_power_put(struct drm_device *dev, enum intel_display_power_domain domain) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_well *power_well = &dev_priv->power_well; + struct i915_power_domains *power_domains; if (!HAS_POWER_WELL(dev)) return; @@ -5623,12 +5625,14 @@ void intel_display_power_put(struct drm_device *dev, if (is_always_on_power_domain(dev, domain)) return; - mutex_lock(&power_well->lock); - __intel_power_well_put(power_well); - mutex_unlock(&power_well->lock); + power_domains = &dev_priv->power_domains; + + mutex_lock(&power_domains->lock); + __intel_power_well_put(&power_domains->power_wells[0]); + mutex_unlock(&power_domains->lock); } -static struct i915_power_well *hsw_pwr; +static struct i915_power_domains *hsw_pwr; /* Display audio driver power well request */ void i915_request_power_well(void) @@ -5637,7 +5641,7 @@ void i915_request_power_well(void) return; mutex_lock(&hsw_pwr->lock); - __intel_power_well_get(hsw_pwr); + __intel_power_well_get(&hsw_pwr->power_wells[0]); mutex_unlock(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_request_power_well); @@ -5649,7 +5653,7 @@ void i915_release_power_well(void) return; mutex_lock(&hsw_pwr->lock); - __intel_power_well_put(hsw_pwr); + __intel_power_well_put(&hsw_pwr->power_wells[0]); mutex_unlock(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_release_power_well); @@ -5657,12 +5661,15 @@ EXPORT_SYMBOL_GPL(i915_release_power_well); int i915_init_power_well(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_power_domains *power_domains = &dev_priv->power_domains; + struct i915_power_well *power_well; - hsw_pwr = &dev_priv->power_well; + mutex_init(&power_domains->lock); + hsw_pwr = power_domains; - hsw_pwr->device = dev; - mutex_init(&hsw_pwr->lock); - hsw_pwr->count = 0; + power_well = &power_domains->power_wells[0]; + power_well->device = dev; + power_well->count = 0; return 0; } @@ -5675,7 +5682,8 @@ void i915_remove_power_well(struct drm_device *dev) void intel_set_power_well(struct drm_device *dev, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_well *power_well = &dev_priv->power_well; + struct i915_power_domains *power_domains = &dev_priv->power_domains; + struct i915_power_well *power_well; if (!HAS_POWER_WELL(dev)) return; @@ -5683,8 +5691,9 @@ void intel_set_power_well(struct drm_device *dev, bool enable) if (!i915_disable_power_well && !enable) return; - mutex_lock(&power_well->lock); + mutex_lock(&power_domains->lock); + power_well = &power_domains->power_wells[0]; /* * This function will only ever contribute one * to the power well reference count. i915_request @@ -5702,20 +5711,24 @@ void intel_set_power_well(struct drm_device *dev, bool enable) __intel_power_well_put(power_well); out: - mutex_unlock(&power_well->lock); + mutex_unlock(&power_domains->lock); } static void intel_resume_power_well(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_well *power_well = &dev_priv->power_well; + struct i915_power_domains *power_domains = &dev_priv->power_domains; + struct i915_power_well *power_well; if (!HAS_POWER_WELL(dev)) return; - mutex_lock(&power_well->lock); + mutex_lock(&power_domains->lock); + + power_well = &power_domains->power_wells[0]; __intel_set_power_well(dev, power_well->count > 0); - mutex_unlock(&power_well->lock); + + mutex_unlock(&power_domains->lock); } /* -- cgit v1.2.3-70-g09d2 From baa707073b6f5374a917f86f4a681149cd39dc64 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 25 Oct 2013 17:36:48 +0300 Subject: drm/i915: use power get/put instead of set for power on after init Currently we make sure that all power domains are enabled during driver init and turn off unneded ones only after the first modeset. Similarly during suspend we enable all power domains, which will remain on through the following resume until the first modeset. This logic is supported by intel_set_power_well() in the power domain framework. It would be nice to simplify the API, so that we only have get/put functions and make it more explicit on the higher level how this "power well on during init" logic works. This will make it also easier if in the future we want to shorten the time the power wells are on. For this add a new device private flag tracking whether we have the power wells on because of init/suspend and use only intel_display_power_get()/put(). As nothing else uses intel_set_power_well() we can remove it. This also fixes commit 6efdf354ddb186c6604d1692075421e8d2c740e9 Author: Imre Deak Date: Wed Oct 16 17:25:52 2013 +0300 drm/i915: enable only the needed power domains during modeset where removing intel_set_power_well() resulted in not releasing the reference on the power well that was taken during init and thus leaving the power well on all the time. Regression reported by Paulo. v2: - move the init_power_on flag to the power_domains struct (Daniel) v3: - add note about this being a regression fix too (Paulo) Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 2 +- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 8 +++++++- drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 37 +----------------------------------- 6 files changed, 28 insertions(+), 39 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 437886641d9..bec1fe93cf2 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1723,7 +1723,7 @@ int i915_driver_unload(struct drm_device *dev) /* The i915.ko module is still not prepared to be loaded when * the power well is not enabled, so just enable it in case * we're going to unload/reload. */ - intel_set_power_well(dev, true); + intel_display_set_init_power(dev, true); i915_remove_power_well(dev); } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1060a96d218..b764f7b7eb6 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -477,7 +477,7 @@ static int i915_drm_freeze(struct drm_device *dev) /* We do a lot of poking in a lot of registers, make sure they work * properly. */ hsw_disable_package_c8(dev_priv); - intel_set_power_well(dev, true); + intel_display_set_init_power(dev, true); drm_kms_helper_poll_disable(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8371182f748..43dbf6a06a9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -100,6 +100,7 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_C, POWER_DOMAIN_TRANSCODER_EDP, POWER_DOMAIN_VGA, + POWER_DOMAIN_INIT, POWER_DOMAIN_NUM, }; @@ -911,12 +912,17 @@ struct i915_power_well { struct drm_device *device; /* power well enable/disable usage count */ int count; - int i915_request; }; #define I915_MAX_POWER_WELLS 1 struct i915_power_domains { + /* + * Power wells needed for initialization at driver init and suspend + * time are on. They are kept on until after the first modeset. + */ + bool init_power_on; + struct mutex lock; struct i915_power_well power_wells[I915_MAX_POWER_WELLS]; }; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cfe9e7093b2..8c3bf8a89cb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6577,6 +6577,21 @@ static unsigned long get_pipe_power_domains(struct drm_device *dev, return mask; } +void intel_display_set_init_power(struct drm_device *dev, bool enable) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->power_domains.init_power_on == enable) + return; + + if (enable) + intel_display_power_get(dev, POWER_DOMAIN_INIT); + else + intel_display_power_put(dev, POWER_DOMAIN_INIT); + + dev_priv->power_domains.init_power_on = enable; +} + static void modeset_update_power_wells(struct drm_device *dev) { unsigned long pipe_domains[I915_MAX_PIPES] = { 0, }; @@ -6608,6 +6623,8 @@ static void modeset_update_power_wells(struct drm_device *dev) crtc->enabled_power_domains = pipe_domains[crtc->pipe]; } + + intel_display_set_init_power(dev, false); } static void haswell_modeset_global_resources(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index af1553ca0f4..bf4394a144a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -692,6 +692,7 @@ bool intel_crtc_active(struct drm_crtc *crtc); void i915_disable_vga_mem(struct drm_device *dev); void hsw_enable_ips(struct intel_crtc *crtc); void hsw_disable_ips(struct intel_crtc *crtc); +void intel_display_set_init_power(struct drm_device *dev, bool enable); /* intel_dp.c */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5869482f3f6..5ae6d533ebc 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5679,41 +5679,6 @@ void i915_remove_power_well(struct drm_device *dev) hsw_pwr = NULL; } -void intel_set_power_well(struct drm_device *dev, bool enable) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_domains *power_domains = &dev_priv->power_domains; - struct i915_power_well *power_well; - - if (!HAS_POWER_WELL(dev)) - return; - - if (!i915_disable_power_well && !enable) - return; - - mutex_lock(&power_domains->lock); - - power_well = &power_domains->power_wells[0]; - /* - * This function will only ever contribute one - * to the power well reference count. i915_request - * is what tracks whether we have or have not - * added the one to the reference count. - */ - if (power_well->i915_request == enable) - goto out; - - power_well->i915_request = enable; - - if (enable) - __intel_power_well_get(power_well); - else - __intel_power_well_put(power_well); - - out: - mutex_unlock(&power_domains->lock); -} - static void intel_resume_power_well(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5745,7 +5710,7 @@ void intel_init_power_well(struct drm_device *dev) return; /* For now, we need the power well to be always enabled. */ - intel_set_power_well(dev, true); + intel_display_set_init_power(dev, true); intel_resume_power_well(dev); /* We're taking over the BIOS, so clear any requests made by it since -- cgit v1.2.3-70-g09d2 From b4ed448447970aab11ee33ac28716baaff68fbb8 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 25 Oct 2013 17:36:49 +0300 Subject: drm/i915: remove device field from struct power_well The only real need for this field was in i915_{request,release}_power_well, but there we can get at it by a container_of magic. Also since in the future we'll have multiple power wells each with its own power_well struct it makes sense to remove the field from there where it'd be just redundancy. Suggested-by: Paulo Zanoni Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_pm.c | 29 ++++++++++++++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 43dbf6a06a9..57715c8e59c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -909,7 +909,6 @@ struct intel_ilk_power_mgmt { /* Power well structure for haswell */ struct i915_power_well { - struct drm_device *device; /* power well enable/disable usage count */ int count; }; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5ae6d533ebc..235b3909555 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5581,17 +5581,19 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) } } -static void __intel_power_well_get(struct i915_power_well *power_well) +static void __intel_power_well_get(struct drm_device *dev, + struct i915_power_well *power_well) { if (!power_well->count++) - __intel_set_power_well(power_well->device, true); + __intel_set_power_well(dev, true); } -static void __intel_power_well_put(struct i915_power_well *power_well) +static void __intel_power_well_put(struct drm_device *dev, + struct i915_power_well *power_well) { WARN_ON(!power_well->count); if (!--power_well->count) - __intel_set_power_well(power_well->device, false); + __intel_set_power_well(dev, false); } void intel_display_power_get(struct drm_device *dev, @@ -5609,7 +5611,7 @@ void intel_display_power_get(struct drm_device *dev, power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); - __intel_power_well_get(&power_domains->power_wells[0]); + __intel_power_well_get(dev, &power_domains->power_wells[0]); mutex_unlock(&power_domains->lock); } @@ -5628,7 +5630,7 @@ void intel_display_power_put(struct drm_device *dev, power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); - __intel_power_well_put(&power_domains->power_wells[0]); + __intel_power_well_put(dev, &power_domains->power_wells[0]); mutex_unlock(&power_domains->lock); } @@ -5637,11 +5639,16 @@ static struct i915_power_domains *hsw_pwr; /* Display audio driver power well request */ void i915_request_power_well(void) { + struct drm_i915_private *dev_priv; + if (WARN_ON(!hsw_pwr)) return; + dev_priv = container_of(hsw_pwr, struct drm_i915_private, + power_domains); + mutex_lock(&hsw_pwr->lock); - __intel_power_well_get(&hsw_pwr->power_wells[0]); + __intel_power_well_get(dev_priv->dev, &hsw_pwr->power_wells[0]); mutex_unlock(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_request_power_well); @@ -5649,11 +5656,16 @@ EXPORT_SYMBOL_GPL(i915_request_power_well); /* Display audio driver power well release */ void i915_release_power_well(void) { + struct drm_i915_private *dev_priv; + if (WARN_ON(!hsw_pwr)) return; + dev_priv = container_of(hsw_pwr, struct drm_i915_private, + power_domains); + mutex_lock(&hsw_pwr->lock); - __intel_power_well_put(&hsw_pwr->power_wells[0]); + __intel_power_well_put(dev_priv->dev, &hsw_pwr->power_wells[0]); mutex_unlock(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_release_power_well); @@ -5668,7 +5680,6 @@ int i915_init_power_well(struct drm_device *dev) hsw_pwr = power_domains; power_well = &power_domains->power_wells[0]; - power_well->device = dev; power_well->count = 0; return 0; -- cgit v1.2.3-70-g09d2 From ddb642fb0566758ace34384538720db0e24bcd4c Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 28 Oct 2013 17:20:35 +0200 Subject: drm/i915: rename i915_init_power_well to init_power_domains_init Similarly rename the other related functions in the power domain interface. Higher level driver code calling these functions knows only about power domains, not the underlying power wells which may be different on different platforms. Also these functions really init/cleanup/resume power domains and only through that all related power wells, so rename them accordingly. Note that I left i915_{request,release}_power_well as is, since that really changes the state only of a single power well (and is HSW specific). It should also get a better name once we make it more generic by controlling things through a new audio power domain. v4: - use intel prefix instead of i915 everywhere (Paulo) - use a $prefix_$block_$action format (Daniel) Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 8 ++++---- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 6 +++--- drivers/gpu/drm/i915/intel_pm.c | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index bec1fe93cf2..6eecce70fa7 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1314,7 +1314,7 @@ static int i915_load_modeset_init(struct drm_device *dev) if (ret) goto cleanup_gem_stolen; - intel_init_power_well(dev); + intel_power_domains_init_hw(dev); /* Keep VGA alive until i915_disable_vga_mem() */ intel_display_power_get(dev, POWER_DOMAIN_VGA); @@ -1653,7 +1653,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) } if (HAS_POWER_WELL(dev)) - i915_init_power_well(dev); + intel_power_domains_init(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = i915_load_modeset_init(dev); @@ -1681,7 +1681,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) out_power_well: if (HAS_POWER_WELL(dev)) - i915_remove_power_well(dev); + intel_power_domains_remove(dev); drm_vblank_cleanup(dev); out_gem_unload: if (dev_priv->mm.inactive_shrinker.scan_objects) @@ -1724,7 +1724,7 @@ int i915_driver_unload(struct drm_device *dev) * the power well is not enabled, so just enable it in case * we're going to unload/reload. */ intel_display_set_init_power(dev, true); - i915_remove_power_well(dev); + intel_power_domains_remove(dev); } i915_teardown_sysfs(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b764f7b7eb6..1041644030b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -595,7 +595,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) mutex_unlock(&dev->struct_mutex); } - intel_init_power_well(dev); + intel_power_domains_init_hw(dev); i915_restore_state(dev); intel_opregion_setup(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bf4394a144a..9d2624fd92c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -823,15 +823,15 @@ bool intel_fbc_enabled(struct drm_device *dev); void intel_update_fbc(struct drm_device *dev); void intel_gpu_ips_init(struct drm_i915_private *dev_priv); void intel_gpu_ips_teardown(void); -int i915_init_power_well(struct drm_device *dev); -void i915_remove_power_well(struct drm_device *dev); +int intel_power_domains_init(struct drm_device *dev); +void intel_power_domains_remove(struct drm_device *dev); bool intel_display_power_enabled(struct drm_device *dev, enum intel_display_power_domain domain); void intel_display_power_get(struct drm_device *dev, enum intel_display_power_domain domain); void intel_display_power_put(struct drm_device *dev, enum intel_display_power_domain domain); -void intel_init_power_well(struct drm_device *dev); +void intel_power_domains_init_hw(struct drm_device *dev); void intel_set_power_well(struct drm_device *dev, bool enable); void intel_enable_gt_powersave(struct drm_device *dev); void intel_disable_gt_powersave(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 235b3909555..222e47f1b53 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5670,7 +5670,7 @@ void i915_release_power_well(void) } EXPORT_SYMBOL_GPL(i915_release_power_well); -int i915_init_power_well(struct drm_device *dev) +int intel_power_domains_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains = &dev_priv->power_domains; @@ -5685,12 +5685,12 @@ int i915_init_power_well(struct drm_device *dev) return 0; } -void i915_remove_power_well(struct drm_device *dev) +void intel_power_domains_remove(struct drm_device *dev) { hsw_pwr = NULL; } -static void intel_resume_power_well(struct drm_device *dev) +static void intel_power_domains_resume(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains = &dev_priv->power_domains; @@ -5713,7 +5713,7 @@ static void intel_resume_power_well(struct drm_device *dev) * to be enabled, and it will only be disabled if none of the registers is * requesting it to be enabled. */ -void intel_init_power_well(struct drm_device *dev) +void intel_power_domains_init_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5722,7 +5722,7 @@ void intel_init_power_well(struct drm_device *dev) /* For now, we need the power well to be always enabled. */ intel_display_set_init_power(dev, true); - intel_resume_power_well(dev); + intel_power_domains_resume(dev); /* We're taking over the BIOS, so clear any requests made by it since * the driver is in charge now. */ -- cgit v1.2.3-70-g09d2 From 1ad577ac6e2c870d6a68f214c9208882eb8d8f00 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 29 Oct 2013 19:09:50 +0200 Subject: drm/i915: add back checking for i915_disable_power_well In commit 6efdf354ddb186c6604d1692075421e8d2c740e9 Author: Imre Deak Date: Wed Oct 16 17:25:52 2013 +0300 the check for i915_disable_power_well flag was removed by overlook, so add it back now. Reported-by: Paulo Zanoni Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 222e47f1b53..97009ee387c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5592,7 +5592,7 @@ static void __intel_power_well_put(struct drm_device *dev, struct i915_power_well *power_well) { WARN_ON(!power_well->count); - if (!--power_well->count) + if (!--power_well->count && i915_disable_power_well) __intel_set_power_well(dev, false); } -- cgit v1.2.3-70-g09d2 From 1020a5c2dcefae564c3e87ce934316dfcc1d8427 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sat, 2 Nov 2013 21:07:06 -0700 Subject: drm/i915/bdw: Clock gating init Clock gating init is really a catch all function for registers we need to write early in loading the driver. Atm just the bare metal stuff we need, more will surely come. Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 09ac9e79830..281e68dca60 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5181,6 +5181,15 @@ static void lpt_suspend_hw(struct drm_device *dev) } } +static void gen8_init_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + I915_WRITE(WM3_LP_ILK, 0); + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); +} + static void haswell_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5833,6 +5842,8 @@ void intel_init_pm(struct drm_device *dev) dev_priv->display.update_wm = NULL; } dev_priv->display.init_clock_gating = haswell_init_clock_gating; + } else if (INTEL_INFO(dev)->gen == 8) { + dev_priv->display.init_clock_gating = gen8_init_clock_gating; } else dev_priv->display.update_wm = NULL; } else if (IS_VALLEYVIEW(dev)) { -- cgit v1.2.3-70-g09d2 From 6745a2ceaac6d4dd3ddac460dc149275b0ae7fc0 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Sat, 2 Nov 2013 21:07:34 -0700 Subject: drm/i915/bdw: Broadwell also has the "power down well" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just like Haswell, but with the small twist that the panel fitter for pipe A is now also in the always-on power well. v2: Use the new HAS_POWER_WELL macro. v3: Rebase on top of intel_using_power_well patches. v4: This time actually update the PFIT check correctly so that the pipe A pfit is in the always-on domain. v5: Rebase on top of the VGA power domain addition. v6: Rebase on top of the new power domain infrastructure. Also pimp the commit message a bit while at it. v7: Use IS_BROADWELL instead of IS_GEN8 (Ville). Signed-off-by: Paulo Zanoni (v1) Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 6 +++++- drivers/gpu/drm/i915/intel_pm.c | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 153011a6b88..d9d6db263ab 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -117,6 +117,10 @@ enum intel_display_power_domain { #define HSW_ALWAYS_ON_POWER_DOMAINS ( \ BIT(POWER_DOMAIN_PIPE_A) | \ BIT(POWER_DOMAIN_TRANSCODER_EDP)) +#define BDW_ALWAYS_ON_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_PIPE_A) | \ + BIT(POWER_DOMAIN_TRANSCODER_EDP) | \ + BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER)) enum hpd_pin { HPD_NONE = 0, @@ -1804,7 +1808,7 @@ struct drm_i915_file_private { #define HAS_IPS(dev) (IS_ULT(dev)) #define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi) -#define HAS_POWER_WELL(dev) (IS_HASWELL(dev)) +#define HAS_POWER_WELL(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev)) #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) #define HAS_PSR(dev) (IS_HASWELL(dev)) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 281e68dca60..b9496abd76d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5520,7 +5520,9 @@ static bool is_always_on_power_domain(struct drm_device *dev, BUG_ON(BIT(domain) & ~POWER_DOMAIN_MASK); - if (IS_HASWELL(dev)) { + if (IS_BROADWELL(dev)) { + always_on_domains = BDW_ALWAYS_ON_POWER_DOMAINS; + } else if (IS_HASWELL(dev)) { always_on_domains = HSW_ALWAYS_ON_POWER_DOMAINS; } else { WARN_ON(1); @@ -6006,4 +6008,3 @@ void intel_pm_init(struct drm_device *dev) INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, intel_gen6_powersave_work); } - -- cgit v1.2.3-70-g09d2 From 50ed5fbd9dcd6e8531cc34bb2a1e2c01ea00697d Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sat, 2 Nov 2013 21:07:40 -0700 Subject: drm/i915/bdw: Implement WaSwitchSolVfFArbitrationPriority GEN8 also needs this workaround. Signed-off-by: Ben Widawsky [danvet: Add a generic comment that we need to recheck all these w/a.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b9496abd76d..b05f141a5a0 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5188,6 +5188,12 @@ static void gen8_init_clock_gating(struct drm_device *dev) I915_WRITE(WM3_LP_ILK, 0); I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0); + + /* FIXME(BDW): Check all the w/a, some might only apply to + * pre-production hw. */ + + /* WaSwitchSolVfFArbitrationPriority */ + I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); } static void haswell_init_clock_gating(struct drm_device *dev) -- cgit v1.2.3-70-g09d2 From 416f4727abf9e5ecc88fea4b55ea294d310534ac Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Sat, 2 Nov 2013 21:07:46 -0700 Subject: drm/i915/bdw: Add Broadwell display FIFO limits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Broadwell has bigger display FIFOs than Haswell. Otherwise the two are very similar. v2: Fix FBC WM_LP shift for BDW v3: Rebase on top of the big Haswell wm rework. Signed-off-by: Ville Syrjälä (v2) Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ad903b927fb..b2abdd78fde 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3379,6 +3379,7 @@ #define WM1_LP_LATENCY_MASK (0x7f<<24) #define WM1_LP_FBC_MASK (0xf<<20) #define WM1_LP_FBC_SHIFT 20 +#define WM1_LP_FBC_SHIFT_BDW 19 #define WM1_LP_SR_MASK (0x7ff<<8) #define WM1_LP_SR_SHIFT 8 #define WM1_LP_CURSOR_MASK (0xff) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b05f141a5a0..0ca8eb765e2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2291,7 +2291,9 @@ static uint32_t ilk_compute_fbc_wm(const struct hsw_pipe_wm_parameters *params, static unsigned int ilk_display_fifo_size(const struct drm_device *dev) { - if (INTEL_INFO(dev)->gen >= 7) + if (INTEL_INFO(dev)->gen >= 8) + return 3072; + else if (INTEL_INFO(dev)->gen >= 7) return 768; else return 512; @@ -2336,7 +2338,9 @@ static unsigned int ilk_plane_wm_max(const struct drm_device *dev, } /* clamp to max that the registers can hold */ - if (INTEL_INFO(dev)->gen >= 7) + if (INTEL_INFO(dev)->gen >= 8) + max = level == 0 ? 255 : 2047; + else if (INTEL_INFO(dev)->gen >= 7) /* IVB/HSW primary/sprite plane watermarks */ max = level == 0 ? 127 : 1023; else if (!is_sprite) @@ -2366,10 +2370,13 @@ static unsigned int ilk_cursor_wm_max(const struct drm_device *dev, } /* Calculate the maximum FBC watermark */ -static unsigned int ilk_fbc_wm_max(void) +static unsigned int ilk_fbc_wm_max(struct drm_device *dev) { /* max that registers can hold */ - return 15; + if (INTEL_INFO(dev)->gen >= 8) + return 31; + else + return 15; } static void ilk_compute_wm_maximums(struct drm_device *dev, @@ -2381,7 +2388,7 @@ static void ilk_compute_wm_maximums(struct drm_device *dev, max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false); max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true); max->cur = ilk_cursor_wm_max(dev, level, config); - max->fbc = ilk_fbc_wm_max(); + max->fbc = ilk_fbc_wm_max(dev); } static bool ilk_validate_wm_level(int level, @@ -2722,10 +2729,18 @@ static void hsw_compute_wm_results(struct drm_device *dev, if (!r->enable) break; - results->wm_lp[wm_lp - 1] = HSW_WM_LP_VAL(level * 2, - r->fbc_val, - r->pri_val, - r->cur_val); + results->wm_lp[wm_lp - 1] = WM3_LP_EN | + ((level * 2) << WM1_LP_LATENCY_SHIFT) | + (r->pri_val << WM1_LP_SR_SHIFT) | + r->cur_val; + + if (INTEL_INFO(dev)->gen >= 8) + results->wm_lp[wm_lp - 1] |= + r->fbc_val << WM1_LP_FBC_SHIFT_BDW; + else + results->wm_lp[wm_lp - 1] |= + r->fbc_val << WM1_LP_FBC_SHIFT; + results->wm_lp_spr[wm_lp - 1] = r->spr_val; } -- cgit v1.2.3-70-g09d2 From 46c764d41f54ca9f03c50b5d7845bc97ac46c11a Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sat, 2 Nov 2013 21:07:49 -0700 Subject: drm/i915/bdw: Use HSW formula for ring freq scaling The current formula we use for HSW is not what is in current docs. However, changing to the HSW formula on my HSW does not improve power usage, and decreases performance by about 5% in limited xonotic testing. For gen8, until we know otherwise, or run experiments, let's use the HSW formula - which should be the same used in the Windows driver (and thus help make an apples-applies comparison) on gen8. v2: Use >= 8 instead of > 7 to be consistent with all other gen checks. Signed-off-by: Ben Widawsky (v1) Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0ca8eb765e2..99658468cd9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3924,7 +3924,10 @@ void gen6_update_ring_freq(struct drm_device *dev) int diff = dev_priv->rps.max_delay - gpu_freq; unsigned int ia_freq = 0, ring_freq = 0; - if (IS_HASWELL(dev)) { + if (INTEL_INFO(dev)->gen >= 8) { + /* max(2 * GT, DDR). NB: GT is 50MHz units */ + ring_freq = max(min_ring_freq, gpu_freq); + } else if (IS_HASWELL(dev)) { ring_freq = mult_frac(gpu_freq, 5, 4); ring_freq = max(min_ring_freq, ring_freq); /* leave ia_freq as the default, chosen by cpufreq */ -- cgit v1.2.3-70-g09d2 From 6edee7f3e7daab105b33148b49c74a8f881d172e Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sat, 2 Nov 2013 21:07:52 -0700 Subject: drm/i915/bdw: Create a separate BDW rps enable This is mostly what we have for HSW with the exceptions of: no writes: GEN6_RC1_WAKE_RATE_LIMIT GEN6_RC6pp_WAKE_RATE_LIMIT GEN6_RC1e_THRESHOLD GEN6_RC6p_THRESHOLD GEN6_RC6pp_THRESHOLD GEN6_RP_DOWN_TIMEOUT - use 1s instead of 1.28s Don't try to overclock, or program ring/IA frequency tables since we don't quite have sufficient docs yet. NOTE: These values do not reflect the changes made recently by Chris. Since we have no evidence yet what the proper way to tweak for this platform is, I think it is good to go, and can be optimized by Chris, or whomever, later. Cc: Chris Wilson Signed-off-by: Ben Widawsky [danvet: Drop spurious hunk and drop TODO - having per-platform rps register frobbing code is in my opinion preferred, now that all the infrastructure functions are extracted.] Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 75 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 99658468cd9..a35ebcf04fa 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3762,6 +3762,78 @@ static void gen6_enable_rps_interrupts(struct drm_device *dev) I915_WRITE(GEN6_PMINTRMSK, ~enabled_intrs); } +static void gen8_enable_rps(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring; + uint32_t rc6_mask = 0, rp_state_cap; + int unused; + + /* 1a: Software RC state - RC0 */ + I915_WRITE(GEN6_RC_STATE, 0); + + /* 1c & 1d: Get forcewake during program sequence. Although the driver + * hasn't enabled a state yet where we need forcewake, BIOS may have.*/ + gen6_gt_force_wake_get(dev_priv); + + /* 2a: Disable RC states. */ + I915_WRITE(GEN6_RC_CONTROL, 0); + + rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); + + /* 2b: Program RC6 thresholds.*/ + I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16); + I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ + I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ + for_each_ring(ring, dev_priv, unused) + I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); + I915_WRITE(GEN6_RC_SLEEP, 0); + I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */ + + /* 3: Enable RC6 */ + if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) + rc6_mask = GEN6_RC_CTL_RC6_ENABLE; + DRM_INFO("RC6 %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off"); + I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | + GEN6_RC_CTL_EI_MODE(1) | + rc6_mask); + + /* 4 Program defaults and thresholds for RPS*/ + I915_WRITE(GEN6_RPNSWREQ, HSW_FREQUENCY(10)); /* Request 500 MHz */ + I915_WRITE(GEN6_RC_VIDEO_FREQ, HSW_FREQUENCY(12)); /* Request 600 MHz */ + /* NB: Docs say 1s, and 1000000 - which aren't equivalent */ + I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 100000000 / 128); /* 1 second timeout */ + + /* Docs recommend 900MHz, and 300 MHz respectively */ + I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, + dev_priv->rps.max_delay << 24 | + dev_priv->rps.min_delay << 16); + + I915_WRITE(GEN6_RP_UP_THRESHOLD, 7600000 / 128); /* 76ms busyness per EI, 90% */ + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 31300000 / 128); /* 313ms busyness per EI, 70%*/ + I915_WRITE(GEN6_RP_UP_EI, 66000); /* 84.48ms, XXX: random? */ + I915_WRITE(GEN6_RP_DOWN_EI, 350000); /* 448ms, XXX: random? */ + + I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); + + /* 5: Enable RPS */ + I915_WRITE(GEN6_RP_CONTROL, + GEN6_RP_MEDIA_TURBO | + GEN6_RP_MEDIA_HW_NORMAL_MODE | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_ENABLE | + GEN6_RP_UP_BUSY_AVG | + GEN6_RP_DOWN_IDLE_AVG); + + /* 6: Ring frequency + overclocking (our driver does this later */ + + gen6_set_rps(dev, (I915_READ(GEN6_GT_PERF_STATUS) & 0xff00) >> 8); + + gen6_enable_rps_interrupts(dev); + + gen6_gt_force_wake_put(dev_priv); +} + static void gen6_enable_rps(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -4891,6 +4963,9 @@ static void intel_gen6_powersave_work(struct work_struct *work) if (IS_VALLEYVIEW(dev)) { valleyview_enable_rps(dev); + } else if (IS_BROADWELL(dev)) { + gen8_enable_rps(dev); + gen6_update_ring_freq(dev); } else { gen6_enable_rps(dev); gen6_update_ring_freq(dev); -- cgit v1.2.3-70-g09d2 From fe4ab3ceef20655d651160841a48f0419dfa0a5a Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sat, 2 Nov 2013 21:07:54 -0700 Subject: drm/i915/bdw: Implement edp PSR workarounds This implements a workaround for PSR dealing with some vblank issue. WaPsrDPAMaskVBlankInSRD && WaPsrDPRSUnmaskVBlankInSRD v2: forgot to git add bogus whitespace fix v3: Update with workaround names. Use for_each_pipe() and CHICKEN_PIPESL_1(pipe) macro (Ville) Cc: Art Runyan Signed-off-by: Ben Widawsky Reviewed-by: Jesse Barnes [danvet: Kill redundant IS_BDW check and remove the copious amount of uneeded lines added.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 6 ++++++ drivers/gpu/drm/i915/intel_pm.c | 12 ++++++++++++ 2 files changed, 18 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ffe88745898..f5701ff8847 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4113,8 +4113,14 @@ # define CHICKEN3_DGMG_DONE_FIX_DISABLE (1 << 2) #define CHICKEN_PAR1_1 0x42080 +#define DPA_MASK_VBLANK_SRD (1 << 15) #define FORCE_ARB_IDLE_PLANES (1 << 14) +#define _CHICKEN_PIPESL_1_A 0x420b0 +#define _CHICKEN_PIPESL_1_B 0x420b4 +#define DPRS_MASK_VBLANK_SRD (1 << 0) +#define CHICKEN_PIPESL_1(pipe) _PIPE(pipe, _CHICKEN_PIPESL_1_A, _CHICKEN_PIPESL_1_B) + #define DISP_ARB_CTL 0x45000 #define DISP_TILE_SURFACE_SWIZZLING (1<<13) #define DISP_FBC_WM_DIS (1<<15) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a35ebcf04fa..6d186757dc3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5277,6 +5277,7 @@ static void lpt_suspend_hw(struct drm_device *dev) static void gen8_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe i; I915_WRITE(WM3_LP_ILK, 0); I915_WRITE(WM2_LP_ILK, 0); @@ -5287,6 +5288,17 @@ static void gen8_init_clock_gating(struct drm_device *dev) /* WaSwitchSolVfFArbitrationPriority */ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); + + /* WaPsrDPAMaskVBlankInSRD */ + I915_WRITE(CHICKEN_PAR1_1, + I915_READ(CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD); + + /* WaPsrDPRSUnmaskVBlankInSRD */ + for_each_pipe(i) { + I915_WRITE(CHICKEN_PIPESL_1(i), + I915_READ(CHICKEN_PIPESL_1(i) | + DPRS_MASK_VBLANK_SRD)); + } } static void haswell_init_clock_gating(struct drm_device *dev) -- cgit v1.2.3-70-g09d2 From 4afe8d3347d69af7bc606fafad134885ed1544e2 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sat, 2 Nov 2013 21:07:55 -0700 Subject: drm/i915/bdw: BWGTLB clock gate disable Signed-off-by: Ben Widawsky Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f5701ff8847..b87945d5dce 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -660,6 +660,7 @@ #define ARB_MODE_SWIZZLE_SNB (1<<4) #define ARB_MODE_SWIZZLE_IVB (1<<5) #define GAMTARBMODE 0x04a08 +#define ARB_MODE_BWGTLB_DISABLE (1<<9) #define ARB_MODE_SWIZZLE_BDW (1<<1) #define RENDER_HWS_PGA_GEN7 (0x04080) #define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6d186757dc3..8249be5f83f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5286,6 +5286,8 @@ static void gen8_init_clock_gating(struct drm_device *dev) /* FIXME(BDW): Check all the w/a, some might only apply to * pre-production hw. */ + I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_BWGTLB_DISABLE)); + /* WaSwitchSolVfFArbitrationPriority */ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); -- cgit v1.2.3-70-g09d2 From fd392b6003ae79c8abfb077be76e0a4b4cea8e3e Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 4 Nov 2013 22:52:39 -0800 Subject: ddrm/i915/bdw: Disable centroid pixel perf optimization BDW-A workaround BDW Bug #1899532 v2: WARN on when not using preliminary HW support Signed-off-by: Ben Widawsky Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/intel_pm.c | 4 ++++ 2 files changed, 7 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b87945d5dce..ffd103a5d47 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5007,6 +5007,9 @@ #define HSW_ROW_CHICKEN3 0xe49c #define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6) +#define HALF_SLICE_CHICKEN3 0xe184 +#define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8) + #define G4X_AUD_VID_DID (dev_priv->info->display_mmio_offset + 0x62020) #define INTEL_AUDIO_DEVCL 0x808629FB #define INTEL_AUDIO_DEVBLC 0x80862801 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8249be5f83f..e036ba06be9 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5286,6 +5286,10 @@ static void gen8_init_clock_gating(struct drm_device *dev) /* FIXME(BDW): Check all the w/a, some might only apply to * pre-production hw. */ + WARN(!i915_preliminary_hw_support, + "GEN8_CENTROID_PIXEL_OPT_DIS not be needed for production\n"); + I915_WRITE(HALF_SLICE_CHICKEN3, + _MASKED_BIT_ENABLE(GEN8_CENTROID_PIXEL_OPT_DIS)); I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_BWGTLB_DISABLE)); /* WaSwitchSolVfFArbitrationPriority */ -- cgit v1.2.3-70-g09d2 From bf66347cd3a3e947d4eff5bafa6c72283c2411ed Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sat, 2 Nov 2013 21:07:57 -0700 Subject: drm/i915/bdw: Sampler power bypass disable BDW-A workaround. BDW Bug #1899812 Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ffd103a5d47..1d557291fb2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5009,6 +5009,7 @@ #define HALF_SLICE_CHICKEN3 0xe184 #define GEN8_CENTROID_PIXEL_OPT_DIS (1<<8) +#define GEN8_SAMPLER_POWER_BYPASS_DIS (1<<1) #define G4X_AUD_VID_DID (dev_priv->info->display_mmio_offset + 0x62020) #define INTEL_AUDIO_DEVCL 0x808629FB diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e036ba06be9..7e0039e8c2d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5290,6 +5290,8 @@ static void gen8_init_clock_gating(struct drm_device *dev) "GEN8_CENTROID_PIXEL_OPT_DIS not be needed for production\n"); I915_WRITE(HALF_SLICE_CHICKEN3, _MASKED_BIT_ENABLE(GEN8_CENTROID_PIXEL_OPT_DIS)); + I915_WRITE(HALF_SLICE_CHICKEN3, + _MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS)); I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_BWGTLB_DISABLE)); /* WaSwitchSolVfFArbitrationPriority */ -- cgit v1.2.3-70-g09d2 From 7f88da0cf6947c3b6a5ccad6c37336367dd69159 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sat, 2 Nov 2013 21:07:58 -0700 Subject: drm/i915/bdw: Limit SDE poly depth FIFO to 2 BDW-A workaround BDW Bug #1899155 Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1d557291fb2..c0b398572c2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -783,6 +783,7 @@ #define _3D_CHICKEN3 0x02090 #define _3D_CHICKEN_SF_DISABLE_OBJEND_CULL (1 << 10) #define _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL (1 << 5) +#define _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(x) ((x)<<1) #define MI_MODE 0x0209c # define VS_TIMER_DISPATCH (1 << 6) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 7e0039e8c2d..5dceb56f6ce 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5294,6 +5294,9 @@ static void gen8_init_clock_gating(struct drm_device *dev) _MASKED_BIT_ENABLE(GEN8_SAMPLER_POWER_BYPASS_DIS)); I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_BWGTLB_DISABLE)); + I915_WRITE(_3D_CHICKEN3, + _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(2)); + /* WaSwitchSolVfFArbitrationPriority */ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); -- cgit v1.2.3-70-g09d2 From a75f36283d12d13aa278abce3a1bb6662e28fcfb Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sat, 2 Nov 2013 21:07:59 -0700 Subject: drm/i915/bdw: conservative SBE VUE cache mode Hold vertex data in cache until last reference BDW-A workaround Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c0b398572c2..e1a1bb71896 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4133,6 +4133,8 @@ /* GEN7 chicken */ #define GEN7_COMMON_SLICE_CHICKEN1 0x7010 # define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC ((1<<10) | (1<<26)) +#define COMMON_SLICE_CHICKEN2 0x7014 +# define GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE (1<<0) #define GEN7_L3CNTLREG1 0xB01C #define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C4FFF8C diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5dceb56f6ce..ccd1b88bc24 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5297,6 +5297,9 @@ static void gen8_init_clock_gating(struct drm_device *dev) I915_WRITE(_3D_CHICKEN3, _3D_CHICKEN_SDE_LIMIT_FIFO_POLY_DEPTH(2)); + I915_WRITE(COMMON_SLICE_CHICKEN2, + _MASKED_BIT_ENABLE(GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE)); + /* WaSwitchSolVfFArbitrationPriority */ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); -- cgit v1.2.3-70-g09d2 From 4c2e7a5f6418775b7a7b47a62d07682c513259e0 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Sat, 2 Nov 2013 21:08:00 -0700 Subject: drm/i915/bdw: WaSingleSubspanDispatchOnAALinesAndPoints Implement WaSingleSubspanDispatchOnAALinesAndPoints BDW-A workaround. Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_pm.c') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e1a1bb71896..2b9e66c0c6c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5001,6 +5001,7 @@ #define GEN7_HALF_SLICE_CHICKEN1 0xe100 /* IVB GT1 + VLV */ #define GEN7_HALF_SLICE_CHICKEN1_GT2 0xf100 #define GEN7_MAX_PS_THREAD_DEP (8<<12) +#define GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE (1<<10) #define GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE (1<<3) #define GEN7_ROW_CHICKEN2 0xe4f4 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ccd1b88bc24..0a07d7c9caf 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5300,6 +5300,9 @@ static void gen8_init_clock_gating(struct drm_device *dev) I915_WRITE(COMMON_SLICE_CHICKEN2, _MASKED_BIT_ENABLE(GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE)); + I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, + _MASKED_BIT_ENABLE(GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE)); + /* WaSwitchSolVfFArbitrationPriority */ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); -- cgit v1.2.3-70-g09d2