@@ -938,6 +938,9 @@ struct intel_gen6_power_mgmt {
u8 rp0_delay;
u8 hw_max;
+ bool rp_up_masked;
+ bool rp_down_masked;
+
int last_adj;
enum { LOW_POWER, BETWEEN, HIGH_POWER } power;
@@ -998,6 +998,43 @@ static void notify_ring(struct drm_device *dev,
i915_queue_hangcheck(dev);
}
+static void gen6_set_pm_mask(struct drm_i915_private *dev_priv,
+ u32 pm_iir, int new_delay)
+{
+ if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) {
+ if (new_delay >= dev_priv->rps.max_delay) {
+ /* Mask UP THRESHOLD Interrupts */
+ I915_WRITE(GEN6_PMINTRMSK,
+ I915_READ(GEN6_PMINTRMSK) |
+ GEN6_PM_RP_UP_THRESHOLD);
+ dev_priv->rps.rp_up_masked = true;
+ }
+ if (dev_priv->rps.rp_down_masked) {
+ /* UnMask DOWN THRESHOLD Interrupts */
+ I915_WRITE(GEN6_PMINTRMSK,
+ I915_READ(GEN6_PMINTRMSK) &
+ ~GEN6_PM_RP_DOWN_THRESHOLD);
+ dev_priv->rps.rp_down_masked = false;
+ }
+ } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
+ if (new_delay <= dev_priv->rps.min_delay) {
+ /* Mask DOWN THRESHOLD Interrupts */
+ I915_WRITE(GEN6_PMINTRMSK,
+ I915_READ(GEN6_PMINTRMSK) |
+ GEN6_PM_RP_DOWN_THRESHOLD);
+ dev_priv->rps.rp_down_masked = true;
+ }
+
+ if (dev_priv->rps.rp_up_masked) {
+ /* UnMask UP THRESHOLD Interrupts */
+ I915_WRITE(GEN6_PMINTRMSK,
+ I915_READ(GEN6_PMINTRMSK) &
+ ~GEN6_PM_RP_UP_THRESHOLD);
+ dev_priv->rps.rp_up_masked = false;
+ }
+ }
+}
+
static void gen6_pm_rps_work(struct work_struct *work)
{
drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
@@ -1055,6 +1092,8 @@ static void gen6_pm_rps_work(struct work_struct *work)
*/
new_delay = clamp_t(int, new_delay,
dev_priv->rps.min_delay, dev_priv->rps.max_delay);
+
+ gen6_set_pm_mask(dev_priv, pm_iir, new_delay);
dev_priv->rps.last_adj = new_delay - dev_priv->rps.cur_delay;
if (IS_VALLEYVIEW(dev_priv->dev))
@@ -3618,6 +3618,9 @@ static void valleyview_enable_rps(struct drm_device *dev)
valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay);
+ dev_priv->rps.rp_up_masked = false;
+ dev_priv->rps.rp_down_masked = false;
+
gen6_enable_rps_interrupts(dev);
gen6_gt_force_wake_put(dev_priv, FORCEWAKE_ALL);