summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Widawsky <benjamin.widawsky@intel.com>2013-09-24 14:49:49 -0700
committerBen Widawsky <benjamin.widawsky@intel.com>2013-09-25 16:49:47 -0700
commit1f05e017764e7ecf55985e01c3a2f0847a631c9a (patch)
tree9421d25620c534968a021658e89229b2da74b75e
parenta3b1490548b7e0f09092dcf6fb31174dad8b19eb (diff)
drm/i915: Update HSW ring frequency scalingring-scale
Aside from updating the algorithm for the min ring frequency scaling on HSW, a couple of other "fixes" are here. Firstly, from what I can tell the old code does this: min_ring_freq = 8 * <ddr_freq> + 2 / 3 ring_freq = (gpu_freq * 5 + 3) / 4 (gpu_freq * 1.33?) gt_mailbox[data] = max(min_ring_freq, ring_freq) This seems fine, except I have no idea where these formulas came from, and it therefore /seems/ to neglect that gpu_freq is in units of 50MHz. I didn't may attention to the maths too thoroughly though. Upon investigated what to do for GEN#Next - which is supposed to use the same formula as HSW, I noticed the HSW algorithm was funny. I'm more than happy to leave HSW as is, and do this for BDW if anyone is opposed. In this patch, I do the following: Fix a wrong comment - the multiply is 266MHz not 133MHz (though the docs say 133 in some places). Use mult_frac instead of hard to read arithmetic. Add some comments across the code to explain what things are doing, and why. Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 3212d3b71b19..7425e7a138ff 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3637,7 +3637,7 @@ void gen6_update_ring_freq(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
int min_freq = 15;
unsigned int gpu_freq;
- unsigned int max_ia_freq, min_ring_freq;
+ unsigned int max_ia_freq;
int scaling_factor = 180;
struct cpufreq_policy *policy;
@@ -3658,10 +3658,6 @@ 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;
-
/*
* For each potential GPU frequency, load a ring frequency we'd like
* to use for memory access. We do this by specifying the IA frequency
@@ -3673,12 +3669,22 @@ 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 = max(min_ring_freq, ring_freq);
+ uint32_t ddr_freq = I915_READ(MCHBAR_MIRROR_BASE_SNB + DCLK) & 0xf;
+ /* convert DDR frequency from units of 266MHz to bandwidth. */
+ ddr_freq = mult_frac(ddr_freq, 800, 3);
+
+ /* gpu_freq is stored in units of 50Mhz. desired result
+ * is max(ddr_freq, 2 * GT) - NB: This matches windows,
+ * and not the docs.
+ */
+ ring_freq = max(ddr_freq, 50 * gpu_freq * 2);
+
/* leave ia_freq as the default, chosen by cpufreq */
DRM_DEBUG_DRIVER("Setup min ring frequency %dMHz for GT freq %dMHz\n",
- ring_freq * 100, gpu_freq * 50);
+ ring_freq, gpu_freq * 50);
+
+ ring_freq /= 100;
} else {
/* On older processors, there is no separate ring
* clock domain, so in order to boost the bandwidth