[Intel-gfx] [PATCH 16/26] drm/i915: turbo & RC6 support for VLV
Rohit Jain
rohit at intel.com
Wed Mar 6 11:51:03 CET 2013
On Sat, 2 Mar 2013, Jesse Barnes wrote:
> From: Ben Widawsky <ben at bwidawsk.net>
>
> Uses slightly different interfaces than other platforms.
>
> Signed-off-by: Jesse Barnes <jbarnes at virtuousgeek.org>
> ---
> drivers/gpu/drm/i915/intel_pm.c | 148 +++++++++++++++++++++++++++++++++++++--
> 1 file changed, 144 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index e3947cb..d16f4f40 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -2477,6 +2477,47 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
> trace_intel_gpu_freq_change(val * 50);
> }
>
> +void valleyview_set_rps(struct drm_device *dev, u8 val)
> +{
> + struct drm_i915_private *dev_priv = dev->dev_private;
> + unsigned long timeout = jiffies + msecs_to_jiffies(100);
> + u32 limits = gen6_rps_limits(dev_priv, &val);
> + u32 pval;
> +
> + WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
> + WARN_ON(val > dev_priv->rps.max_delay);
> + WARN_ON(val < dev_priv->rps.min_delay);
> +
> + if (val == dev_priv->rps.cur_delay)
> + return;
> +
> + valleyview_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val);
> +
> + do {
> + valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &pval);
> + if (time_after(jiffies, timeout)) {
> + DRM_DEBUG_DRIVER("timed out waiting for Punit\n");
> + break;
> + }
> + udelay(10);
> + } while (pval & 1);
> +
> + valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &pval);
> + if ((pval >> 8) != val)
> + DRM_DEBUG_DRIVER("punit overrode freq: %d requested, but got %d\n",
> + val, pval >> 8);
> +
> + /* Make sure we continue to get interrupts
> + * until we hit the minimum or maximum frequencies.
> + */
> + I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
> +
> + dev_priv->rps.cur_delay = val;
Shouldn't we store pval >> 8 instead of val in cur_delay in order to
reclaim the rps state? If we store val here, the requested frequency will
eventually exceed max_delay if punit overrides with a lower frequency.
> +
> + trace_intel_gpu_freq_change(val * 50);
> +}
> +
> +
> static void gen6_disable_rps(struct drm_device *dev)
> {
> struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -2714,6 +2755,100 @@ static void gen6_update_ring_freq(struct drm_device *dev)
> }
> }
>
> +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;
> + int i;
> +
> + 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);
> + I915_WRITE(GTFIFODBG, gtfifodbg);
> + }
> +
> + gen6_gt_force_wake_get(dev_priv);
> +
> + I915_WRITE(GEN6_RC_SLEEP, 0);
> +
> + I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 0x00280000);
> + I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
> + I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 0x19);
> +
> + for_each_ring(ring, dev_priv, i)
> + I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10);
> +
> + I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
> + I915_WRITE(GEN6_RC6_THRESHOLD, 0xc350);
> +
> + 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);
> +
> + 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 |
> + GEN6_RP_DOWN_IDLE_CONT);
> +
> + /* allows RC6 residency counter to work */
> + I915_WRITE(0x138104, 0xffff00ff);
> + I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE);
> +
> + valleyview_punit_read(dev_priv, PUNIT_FUSE_BUS1, &val);
> + DRM_DEBUG_DRIVER("max GPU freq: %d\n", val);
> + dev_priv->rps.max_delay = val;
> +
> + valleyview_punit_read(dev_priv, PUNIT_REG_GPU_LFM, &val);
> + DRM_DEBUG_DRIVER("min GPU freq: %d\n", val);
> + dev_priv->rps.min_delay = val;
> +
> + valleyview_punit_read(dev_priv, PUNIT_FUSE_BUS2, &val);
> + DRM_DEBUG_DRIVER("max GPLL freq: %d\n", val);
> +
> + valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &val);
> + DRM_DEBUG_DRIVER("DDR speed: ");
> + if (((val >> 6) & 3) == 0) {
> + dev_priv->mem_freq = 800;
> + printk("800 MHz\n");
> + } else if (((val >> 6) & 3) == 1) {
> + printk("1066 MHz\n");
> + dev_priv->mem_freq = 1066;
> + } else if (((val >> 6) & 3) == 2) {
> + printk("1333 MHz\n");
> + dev_priv->mem_freq = 1333;
> + } else if (((val >> 6) & 3) == 3)
> + printk("invalid\n");
> + DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 8 ? "yes" : "no");
> + DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val);
> +
> + DRM_DEBUG_DRIVER("current GPU freq: %x\n", (val >> 8) & 0xff);
> + dev_priv->rps.cur_delay = (val >> 8) & 0xff;
> +
> + val = 0xd500;
> + DRM_DEBUG_DRIVER("setting GPU freq to %d\n", (val >> 8) & 0xff);
> +
> + valleyview_set_rps(dev_priv->dev, (val >> 8) & 0xff);
> +
> + /* requires MSI enabled */
> + I915_WRITE(GEN6_PMIER, GEN6_PM_DEFERRED_EVENTS);
> + spin_lock_irq(&dev_priv->rps.lock);
> + WARN_ON(dev_priv->rps.pm_iir != 0);
> + I915_WRITE(GEN6_PMIMR, 0);
> + spin_unlock_irq(&dev_priv->rps.lock);
> + /* enable all PM interrupts */
> + I915_WRITE(GEN6_PMINTRMSK, 0);
> +
> + gen6_gt_force_wake_put(dev_priv);
> +}
> +
> void ironlake_teardown_rc6(struct drm_device *dev)
> {
> struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -3440,7 +3575,7 @@ void intel_disable_gt_powersave(struct drm_device *dev)
> if (IS_IRONLAKE_M(dev)) {
> ironlake_disable_drps(dev);
> ironlake_disable_rc6(dev);
> - } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) {
> + } else if (INTEL_INFO(dev)->gen >= 6) {
> cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work);
> mutex_lock(&dev_priv->rps.hw_lock);
> gen6_disable_rps(dev);
> @@ -3456,8 +3591,13 @@ static void intel_gen6_powersave_work(struct work_struct *work)
> struct drm_device *dev = dev_priv->dev;
>
> mutex_lock(&dev_priv->rps.hw_lock);
> - gen6_enable_rps(dev);
> - gen6_update_ring_freq(dev);
> +
> + if (IS_VALLEYVIEW(dev)) {
> + valleyview_enable_rps(dev);
> + } else {
> + gen6_enable_rps(dev);
> + gen6_update_ring_freq(dev);
> + }
> mutex_unlock(&dev_priv->rps.hw_lock);
> }
>
> @@ -3469,7 +3609,7 @@ void intel_enable_gt_powersave(struct drm_device *dev)
> ironlake_enable_drps(dev);
> ironlake_enable_rc6(dev);
> intel_init_emon(dev);
> - } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
> + } else if (IS_GEN6(dev) || IS_GEN7(dev)) {
> /*
> * PCU communication is slow and this doesn't need to be
> * done at any specific time, so do this out of our fast path
> --
> 1.7.9.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
More information about the Intel-gfx
mailing list