diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 83 | 
1 files changed, 38 insertions, 45 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e6ffef2f707a..b6c886ac901b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1046,68 +1046,51 @@ static void vlv_c0_read(struct drm_i915_private *dev_priv,  	ei->media_c0 = I915_READ(VLV_MEDIA_C0_COUNT);  } -static bool vlv_c0_above(struct drm_i915_private *dev_priv, -			 const struct intel_rps_ei *old, -			 const struct intel_rps_ei *now, -			 int threshold) -{ -	u64 time, c0; -	unsigned int mul = 100; - -	if (old->cz_clock == 0) -		return false; - -	if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH) -		mul <<= 8; - -	time = now->cz_clock - old->cz_clock; -	time *= threshold * dev_priv->czclk_freq; - -	/* Workload can be split between render + media, e.g. SwapBuffers -	 * being blitted in X after being rendered in mesa. To account for -	 * this we need to combine both engines into our activity counter. -	 */ -	c0 = now->render_c0 - old->render_c0; -	c0 += now->media_c0 - old->media_c0; -	c0 *= mul * VLV_CZ_CLOCK_TO_MILLI_SEC; - -	return c0 >= time; -} -  void gen6_rps_reset_ei(struct drm_i915_private *dev_priv)  { -	vlv_c0_read(dev_priv, &dev_priv->rps.down_ei); -	dev_priv->rps.up_ei = dev_priv->rps.down_ei; +	memset(&dev_priv->rps.ei, 0, sizeof(dev_priv->rps.ei));  }  static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir)  { +	const struct intel_rps_ei *prev = &dev_priv->rps.ei;  	struct intel_rps_ei now;  	u32 events = 0; -	if ((pm_iir & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED)) == 0) +	if ((pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) == 0)  		return 0;  	vlv_c0_read(dev_priv, &now);  	if (now.cz_clock == 0)  		return 0; -	if (pm_iir & GEN6_PM_RP_DOWN_EI_EXPIRED) { -		if (!vlv_c0_above(dev_priv, -				  &dev_priv->rps.down_ei, &now, -				  dev_priv->rps.down_threshold)) -			events |= GEN6_PM_RP_DOWN_THRESHOLD; -		dev_priv->rps.down_ei = now; -	} +	if (prev->cz_clock) { +		u64 time, c0; +		unsigned int mul; + +		mul = VLV_CZ_CLOCK_TO_MILLI_SEC * 100; /* scale to threshold% */ +		if (I915_READ(VLV_COUNTER_CONTROL) & VLV_COUNT_RANGE_HIGH) +			mul <<= 8; + +		time = now.cz_clock - prev->cz_clock; +		time *= dev_priv->czclk_freq; + +		/* Workload can be split between render + media, +		 * e.g. SwapBuffers being blitted in X after being rendered in +		 * mesa. To account for this we need to combine both engines +		 * into our activity counter. +		 */ +		c0 = now.render_c0 - prev->render_c0; +		c0 += now.media_c0 - prev->media_c0; +		c0 *= mul; -	if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) { -		if (vlv_c0_above(dev_priv, -				 &dev_priv->rps.up_ei, &now, -				 dev_priv->rps.up_threshold)) -			events |= GEN6_PM_RP_UP_THRESHOLD; -		dev_priv->rps.up_ei = now; +		if (c0 > time * dev_priv->rps.up_threshold) +			events = GEN6_PM_RP_UP_THRESHOLD; +		else if (c0 < time * dev_priv->rps.down_threshold) +			events = GEN6_PM_RP_DOWN_THRESHOLD;  	} +	dev_priv->rps.ei = now;  	return events;  } @@ -4228,7 +4211,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)  	/* Let's track the enabled rps events */  	if (IS_VALLEYVIEW(dev_priv))  		/* WaGsvRC0ResidencyMethod:vlv */ -		dev_priv->pm_rps_events = GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED; +		dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED;  	else  		dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS; @@ -4266,6 +4249,16 @@ void intel_irq_init(struct drm_i915_private *dev_priv)  	if (!IS_GEN2(dev_priv))  		dev->vblank_disable_immediate = true; +	/* Most platforms treat the display irq block as an always-on +	 * power domain. vlv/chv can disable it at runtime and need +	 * special care to avoid writing any of the display block registers +	 * outside of the power domain. We defer setting up the display irqs +	 * in this case to the runtime pm. +	 */ +	dev_priv->display_irqs_enabled = true; +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) +		dev_priv->display_irqs_enabled = false; +  	dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;  	dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;  | 
