Commit 93ee2920 authored by Tom O'Rourke's avatar Tom O'Rourke Committed by Daniel Vetter

drm/i915: Use efficient frequency for HSW/BDW

Added gen6_init_rps_frequencies() to initialize
the rps frequency values.  This function replaces
parse_rp_state_cap().  In addition to reading RPn,
RP0, and RP1 from RP_STATE_CAP register, the new
function reads efficient frequency (aka RPe) from
pcode for Haswell and Broadwell and sets the turbo
softlimits.  The turbo minimum frequency softlimit
is set to RPe for Haswell and Broadwell and to RPn
otherwise.

For RPe, the efficiency is based on the frequency/power
ratio (MHz/W); this is considering GT power and not
package power.  The efficent frequency is the highest
frequency for which the frequency/power ratio is within
some threshold of the highest frequency/power ratio.
A fixed decrease in frequency results in smaller
decrease in power at frequencies less than RPe than
at frequencies above RPe.

v2: Following suggestions from Chris Wilson and
Daniel Vetter to extend and rename parse_rp_state_cap
and to open-code a poorly named function.
Signed-off-by: default avatarTom O'Rourke <Tom.O'Rourke@intel.com>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
[danvet: Remove unused variables.]
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent f548c0e9
...@@ -6038,6 +6038,7 @@ enum punit_power_well { ...@@ -6038,6 +6038,7 @@ enum punit_power_well {
#define GEN6_ENCODE_RC6_VID(mv) (((mv) - 245) / 5) #define GEN6_ENCODE_RC6_VID(mv) (((mv) - 245) / 5)
#define GEN6_DECODE_RC6_VID(vids) (((vids) * 5) + 245) #define GEN6_DECODE_RC6_VID(vids) (((vids) * 5) + 245)
#define DISPLAY_IPS_CONTROL 0x19 #define DISPLAY_IPS_CONTROL 0x19
#define HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL 0x1A
#define GEN6_PCODE_DATA 0x138128 #define GEN6_PCODE_DATA 0x138128
#define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8 #define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8
#define GEN6_PCODE_FREQ_RING_RATIO_SHIFT 16 #define GEN6_PCODE_FREQ_RING_RATIO_SHIFT 16
......
...@@ -4609,25 +4609,45 @@ int intel_enable_rc6(const struct drm_device *dev) ...@@ -4609,25 +4609,45 @@ int intel_enable_rc6(const struct drm_device *dev)
return i915.enable_rc6; return i915.enable_rc6;
} }
static void parse_rp_state_cap(struct drm_i915_private *dev_priv, u32 rp_state_cap) static void gen6_init_rps_frequencies(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t rp_state_cap;
u32 ddcc_status = 0;
int ret;
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
/* All of these values are in units of 50MHz */ /* All of these values are in units of 50MHz */
dev_priv->rps.cur_freq = 0; dev_priv->rps.cur_freq = 0;
/* static values from HW: RP0 < RPe < RP1 < RPn (min_freq) */ /* static values from HW: RP0 > RP1 > RPn (min_freq) */
dev_priv->rps.rp1_freq = (rp_state_cap >> 8) & 0xff;
dev_priv->rps.rp0_freq = (rp_state_cap >> 0) & 0xff; dev_priv->rps.rp0_freq = (rp_state_cap >> 0) & 0xff;
dev_priv->rps.rp1_freq = (rp_state_cap >> 8) & 0xff;
dev_priv->rps.min_freq = (rp_state_cap >> 16) & 0xff; dev_priv->rps.min_freq = (rp_state_cap >> 16) & 0xff;
/* XXX: only BYT has a special efficient freq */
dev_priv->rps.efficient_freq = dev_priv->rps.rp1_freq;
/* hw_max = RP0 until we check for overclocking */ /* hw_max = RP0 until we check for overclocking */
dev_priv->rps.max_freq = dev_priv->rps.rp0_freq; dev_priv->rps.max_freq = dev_priv->rps.rp0_freq;
dev_priv->rps.efficient_freq = dev_priv->rps.rp1_freq;
if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
ret = sandybridge_pcode_read(dev_priv,
HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL,
&ddcc_status);
if (0 == ret)
dev_priv->rps.efficient_freq =
(ddcc_status >> 8) & 0xff;
}
/* Preserve min/max settings in case of re-init */ /* Preserve min/max settings in case of re-init */
if (dev_priv->rps.max_freq_softlimit == 0) if (dev_priv->rps.max_freq_softlimit == 0)
dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq; dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq;
if (dev_priv->rps.min_freq_softlimit == 0) if (dev_priv->rps.min_freq_softlimit == 0) {
dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq; if (IS_HASWELL(dev) || IS_BROADWELL(dev))
dev_priv->rps.min_freq_softlimit =
dev_priv->rps.efficient_freq;
else
dev_priv->rps.min_freq_softlimit =
dev_priv->rps.min_freq;
}
} }
static void gen9_enable_rps(struct drm_device *dev) static void gen9_enable_rps(struct drm_device *dev)
...@@ -4673,7 +4693,7 @@ static void gen8_enable_rps(struct drm_device *dev) ...@@ -4673,7 +4693,7 @@ static void gen8_enable_rps(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *ring; struct intel_engine_cs *ring;
uint32_t rc6_mask = 0, rp_state_cap; uint32_t rc6_mask = 0;
int unused; int unused;
/* 1a: Software RC state - RC0 */ /* 1a: Software RC state - RC0 */
...@@ -4686,8 +4706,8 @@ static void gen8_enable_rps(struct drm_device *dev) ...@@ -4686,8 +4706,8 @@ static void gen8_enable_rps(struct drm_device *dev)
/* 2a: Disable RC states. */ /* 2a: Disable RC states. */
I915_WRITE(GEN6_RC_CONTROL, 0); I915_WRITE(GEN6_RC_CONTROL, 0);
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); /* Initialize rps frequencies */
parse_rp_state_cap(dev_priv, rp_state_cap); gen6_init_rps_frequencies(dev);
/* 2b: Program RC6 thresholds.*/ /* 2b: Program RC6 thresholds.*/
I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16); I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
...@@ -4754,7 +4774,6 @@ static void gen6_enable_rps(struct drm_device *dev) ...@@ -4754,7 +4774,6 @@ static void gen6_enable_rps(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *ring; struct intel_engine_cs *ring;
u32 rp_state_cap;
u32 rc6vids, pcu_mbox = 0, rc6_mask = 0; u32 rc6vids, pcu_mbox = 0, rc6_mask = 0;
u32 gtfifodbg; u32 gtfifodbg;
int rc6_mode; int rc6_mode;
...@@ -4778,9 +4797,8 @@ static void gen6_enable_rps(struct drm_device *dev) ...@@ -4778,9 +4797,8 @@ static void gen6_enable_rps(struct drm_device *dev)
gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL); gen6_gt_force_wake_get(dev_priv, FORCEWAKE_ALL);
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); /* Initialize rps frequencies */
gen6_init_rps_frequencies(dev);
parse_rp_state_cap(dev_priv, rp_state_cap);
/* disable the counters and set deterministic thresholds */ /* disable the counters and set deterministic thresholds */
I915_WRITE(GEN6_RC_CONTROL, 0); I915_WRITE(GEN6_RC_CONTROL, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment