From patchwork Mon Feb 25 23:13:38 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rodrigo Vivi X-Patchwork-Id: 2183151 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 8EA3ADF230 for ; Mon, 25 Feb 2013 23:14:56 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 81BEAE5FB1 for ; Mon, 25 Feb 2013 15:14:56 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mail-gh0-f177.google.com (mail-gh0-f177.google.com [209.85.160.177]) by gabe.freedesktop.org (Postfix) with ESMTP id 456C2E5FB1 for ; Mon, 25 Feb 2013 15:13:58 -0800 (PST) Received: by mail-gh0-f177.google.com with SMTP id g22so605673ghb.22 for ; Mon, 25 Feb 2013 15:13:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=0a8dyaB3wY/j0dXocRhwCkrstTt4gt60kuKWYbWaKtA=; b=KDMsrRLGdYE/00L32iye82Kvd+G/vL7Sa7skYB6tUFVBItum2BAkjsfAuCL32FIOKV +hE8uGbAoumF63WO0+K7cG4PBYXOyMC50UEispjiWhd9a9KBayDZfNF4Yc/3/j2RPMZC CAir9rqO8rQscHrZvp47EZAE60Yf4IgW4s0LkUG0CP7K5IwjfkzIo4J+QRnfPfnvq0t6 2CnPKNGtoPE+2v0s3Q8yBGKIF5T9i4Paa7VOrs9T/oN/K1iPorKWyu952qmNyjMJLrGA fQtCk/m/12ZuiibVKxBctWYZFZ4a6pU56DZZ35REdQnkGb1bCuT5L/+D9DfeETs14z23 Woxg== X-Received: by 10.100.78.13 with SMTP id a13mr6190404anb.44.1361834037628; Mon, 25 Feb 2013 15:13:57 -0800 (PST) Received: from localhost.localdomain ([186.204.164.107]) by mx.google.com with ESMTPS id t5sm15342834anl.22.2013.02.25.15.13.56 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 25 Feb 2013 15:13:57 -0800 (PST) From: Rodrigo Vivi To: intel-gfx@lists.freedesktop.org Date: Mon, 25 Feb 2013 20:13:38 -0300 Message-Id: <1361834023-30062-2-git-send-email-rodrigo.vivi@gmail.com> X-Mailer: git-send-email 1.8.1.2 In-Reply-To: <1361834023-30062-1-git-send-email-rodrigo.vivi@gmail.com> References: <1361834023-30062-1-git-send-email-rodrigo.vivi@gmail.com> Subject: [Intel-gfx] [PATCH 1/6] drm/i915: creating Haswell rc6 function X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Power management, in special RC6 enabling, differs across platforms. This patch just split out enabling function for HSW. Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_pm.c | 158 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 145 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 61fee7f..e8656fd 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2581,15 +2581,10 @@ static void gen6_enable_rps(struct drm_device *dev) rc6_mode = intel_enable_rc6(dev_priv->dev); if (rc6_mode & INTEL_RC6_ENABLE) rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; - - /* We don't use those on Haswell */ - if (!IS_HASWELL(dev)) { - if (rc6_mode & INTEL_RC6p_ENABLE) - rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; - - if (rc6_mode & INTEL_RC6pp_ENABLE) - rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; - } + if (rc6_mode & INTEL_RC6p_ENABLE) + rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; + if (rc6_mode & INTEL_RC6pp_ENABLE) + rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", @@ -2625,7 +2620,141 @@ static void gen6_enable_rps(struct drm_device *dev) GEN6_RP_MEDIA_IS_GFX | GEN6_RP_ENABLE | GEN6_RP_UP_BUSY_AVG | - (IS_HASWELL(dev) ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT)); + GEN6_RP_DOWN_IDLE_CONT); + + ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0); + if (!ret) { + pcu_mbox = 0; + ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox); + if (ret && pcu_mbox & (1<<31)) { /* OC supported */ + dev_priv->rps.max_delay = pcu_mbox & 0xff; + DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50); + } + } else { + DRM_DEBUG_DRIVER("Failed to set the min frequency\n"); + } + + gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8); + + /* 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); + + rc6vids = 0; + ret = sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids); + if (IS_GEN6(dev) && ret) { + DRM_DEBUG_DRIVER("Couldn't check for BIOS workaround\n"); + } else if (IS_GEN6(dev) && (GEN6_DECODE_RC6_VID(rc6vids & 0xff) < 450)) { + DRM_DEBUG_DRIVER("You should update your BIOS. Correcting minimum rc6 voltage (%dmV->%dmV)\n", + GEN6_DECODE_RC6_VID(rc6vids & 0xff), 450); + rc6vids &= 0xffff00; + rc6vids |= GEN6_ENCODE_RC6_VID(450); + ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_RC6VIDS, rc6vids); + if (ret) + DRM_ERROR("Couldn't fix incorrect rc6 voltage\n"); + } + + gen6_gt_force_wake_put(dev_priv); +} + +static void hsw_enable_rps(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring; + u32 rp_state_cap; + u32 gt_perf_status; + u32 rc6vids, pcu_mbox, rc6_mask = 0; + u32 gtfifodbg; + int rc6_mode; + int i, ret; + + WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + + /* Here begins a magic sequence of register writes to enable + * auto-downclocking. + * + * Perhaps there might be some value in exposing these to + * userspace... + */ + I915_WRITE(GEN6_RC_STATE, 0); + + /* Clear the DBG now so we don't confuse earlier errors */ + 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); + + rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); + gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); + + /* In units of 100MHz */ + dev_priv->rps.max_delay = rp_state_cap & 0xff; + dev_priv->rps.min_delay = (rp_state_cap & 0xff0000) >> 16; + dev_priv->rps.cur_delay = 0; + + /* disable the counters and set deterministic thresholds */ + I915_WRITE(GEN6_RC_CONTROL, 0); + + I915_WRITE(GEN6_RC1_WAKE_RATE_LIMIT, 1000 << 16); + I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30); + I915_WRITE(GEN6_RC6pp_WAKE_RATE_LIMIT, 30); + I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); + I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); + + for_each_ring(ring, dev_priv, i) + I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); + + I915_WRITE(GEN6_RC_SLEEP, 0); + I915_WRITE(GEN6_RC1e_THRESHOLD, 1000); + I915_WRITE(GEN6_RC6_THRESHOLD, 50000); + I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); + I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ + + /* Check if we are enabling RC6 */ + rc6_mode = intel_enable_rc6(dev_priv->dev); + if (rc6_mode & INTEL_RC6_ENABLE) + rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; + + DRM_INFO("Enabling RC6 states: RC6 %s\n", + (rc6_mask & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); + + I915_WRITE(GEN6_RC_CONTROL, + rc6_mask | + GEN6_RC_CTL_EI_MODE(1) | + GEN6_RC_CTL_HW_ENABLE); + + I915_WRITE(GEN6_RPNSWREQ, + GEN6_FREQUENCY(10) | + GEN6_OFFSET(0) | + GEN6_AGGRESSIVE_TURBO); + I915_WRITE(GEN6_RC_VIDEO_FREQ, + GEN6_FREQUENCY(12)); + + I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); + I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, + dev_priv->rps.max_delay << 24 | + dev_priv->rps.min_delay << 16); + + 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 | + GEN7_RP_DOWN_IDLE_AVG); ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0); if (!ret) { @@ -3448,7 +3577,7 @@ void intel_disable_gt_powersave(struct drm_device *dev) } } -static void intel_gen6_powersave_work(struct work_struct *work) +static void intel_powersave_work(struct work_struct *work) { struct drm_i915_private *dev_priv = container_of(work, struct drm_i915_private, @@ -3456,7 +3585,10 @@ 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); + if (IS_HASWELL(dev)) + hsw_enable_rps(dev); + else + gen6_enable_rps(dev); gen6_update_ring_freq(dev); mutex_unlock(&dev_priv->rps.hw_lock); } @@ -4459,7 +4591,7 @@ void intel_gt_init(struct drm_device *dev) dev_priv->gt.force_wake_put = __gen6_gt_force_wake_put; } INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, - intel_gen6_powersave_work); + intel_powersave_work); } int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val)