From patchwork Fri Nov 1 19:13:36 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jesse Barnes X-Patchwork-Id: 3127131 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 6FE8ABEEB2 for ; Fri, 1 Nov 2013 19:20:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0C3EE203F4 for ; Fri, 1 Nov 2013 19:20:24 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id D8083203C4 for ; Fri, 1 Nov 2013 19:20:22 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4EB34F069A; Fri, 1 Nov 2013 12:20:21 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org X-Greylist: delayed 398 seconds by postgrey-1.32 at gabe; Fri, 01 Nov 2013 12:20:19 PDT Received: from oproxy4-pub.mail.unifiedlayer.com (oproxy4-pub.mail.unifiedlayer.com [74.220.216.66]) by gabe.freedesktop.org (Postfix) with SMTP id 2FF16F069A for ; Fri, 1 Nov 2013 12:20:19 -0700 (PDT) Received: (qmail 6195 invoked by uid 0); 1 Nov 2013 19:13:39 -0000 Received: from unknown (HELO box514.bluehost.com) (74.220.219.114) by oproxy4.mail.unifiedlayer.com with SMTP; 1 Nov 2013 19:13:39 -0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuousgeek.org; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:To:From; bh=PInesxSZgxlRgN3WSISNIxy4latcQyomYCIX8UufXJs=; b=QrSOWpR42gBZT32TCKH/t7Y2qf0SgKrmjjFI9ZHGJxZqKDIEsg6PxWw3ZMai6JrzW2c0aYbY/bwoEK/coCz7e978D84l2Rk6aXnk37JvcHUnn4mOUvZGO/Xj/gp525EZ; Received: from [67.161.37.189] (port=51481 helo=localhost.localdomain) by box514.bluehost.com with esmtpsa (TLSv1:CAMELLIA256-SHA:256) (Exim 4.80) (envelope-from ) id 1VcKA7-0002RJ-0R for intel-gfx@lists.freedesktop.org; Fri, 01 Nov 2013 13:13:39 -0600 From: Jesse Barnes To: intel-gfx@lists.freedesktop.org Date: Fri, 1 Nov 2013 12:13:36 -0700 Message-Id: <1383333216-1428-1-git-send-email-jbarnes@virtuousgeek.org> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1383328945-1286-1-git-send-email-jbarnes@virtuousgeek.org> References: <1383328945-1286-1-git-send-email-jbarnes@virtuousgeek.org> X-Identified-User: {10642:box514.bluehost.com:virtuous:virtuousgeek.org} {sentby:smtp auth 67.161.37.189 authed with jbarnes@virtuousgeek.org} Subject: [Intel-gfx] [PATCH] drm/i915/vlv: modeset_global_* for VLV v3 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@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org X-Spam-Status: No, score=-4.6 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On VLV/BYT, we can adjust the CDclk frequency up or down based on the max pixel clock we need to drive. Lowering it can save power, while raising it is necessary to support high resolution. Add proper modeset_global_pipes and modeset_global_resources support to perform this adjustment as necessary. v2: use punit interface for 320 and 266 MHz CDclk adjustments (Ville) v3: reset GMBUS dividers too, since we changed CDclk (Ville) Signed-off-by: Jesse Barnes --- drivers/gpu/drm/i915/i915_reg.h | 7 ++ drivers/gpu/drm/i915/intel_display.c | 178 +++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_i2c.c | 4 - 3 files changed, 185 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 737d8a3..8a34dcc 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -363,6 +363,11 @@ #define PUNIT_OPCODE_REG_READ 6 #define PUNIT_OPCODE_REG_WRITE 7 +#define PUNIT_REG_DSPFREQ 0x36 +#define DSPFREQSTAT_SHIFT 30 +#define DSPFREQSTAT_MASK (0x3 << DSPFREQSTAT_SHIFT) +#define DSPFREQGUAR_SHIFT 14 +#define DSPFREQGUAR_MASK (0x3 << DSPFREQGUAR_SHIFT) #define PUNIT_REG_PWRGT_CTRL 0x60 #define PUNIT_REG_PWRGT_STATUS 0x61 #define PUNIT_CLK_GATE 1 @@ -1453,6 +1458,8 @@ #define CZCLK_FREQ_MASK 0xf #define GMBUSFREQ_VLV (VLV_DISPLAY_BASE + 0x6510) +#define CZCLK_CDCLK_FREQ_RATIO (VLV_DISPLAY_BASE + 0x6508) + /* * Palette regs */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index faa7548..ee97789 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3894,6 +3894,179 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc) I915_WRITE(BCLRPAT(crtc->pipe), 0); } +static int valleyview_get_vco(struct drm_i915_private *dev_priv) +{ + int vco; + + switch (dev_priv->mem_freq) { + default: + case 800: + vco = 800; + break; + case 1066: + vco = 1600; + break; + case 1333: + vco = 2000; + break; + } + + return vco; +} + +/* Adjust CDclk dividers to allow high res or save power if possible */ +static void valleyview_set_cdclk(struct drm_device *dev, int cdclk) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val; + + if (cdclk == 400) { + u32 divider, vco; + + vco = valleyview_get_vco(dev_priv); + divider = (vco * 10) / cdclk; + divider = ((divider * 2) / 10) - 1; + + mutex_lock(&dev_priv->dpio_lock); + /* adjust cdclk divider */ + val = vlv_cck_read(dev_priv, 0x6b); + val &= ~0xf; + val |= divider; + vlv_cck_write(dev_priv, 0x6b, val); + mutex_unlock(&dev_priv->dpio_lock); + } else { + u32 cmd; + + if (cdclk == 320) + cmd = 2; + else if (cdclk == 266) + cmd = 1; + else + cmd = 0; + + mutex_lock(&dev_priv->rps.hw_lock); + val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); + val &= ~DSPFREQGUAR_MASK; + val |= (cmd << DSPFREQGUAR_SHIFT); + vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val); + if (wait_for((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & + DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT), + 50)) { + DRM_ERROR("timed out waiting for CDclk change\n"); + } + mutex_unlock(&dev_priv->rps.hw_lock); + } + + mutex_lock(&dev_priv->dpio_lock); + /* adjust self-refresh exit latency value */ + val = vlv_bunit_read(dev_priv, 0x11); + val &= ~0x7f; + + /* + * For high bandwidth configs, we set a higher latency in the bunit + * so that the core display fetch happens in time to avoid underruns. + */ + if (cdclk == 400) + val |= 0x12; + else + val |= 0xc; + vlv_bunit_write(dev_priv, 0x11, val); + mutex_unlock(&dev_priv->dpio_lock); + + /* Since we changed the CDclk, we need to update the GMBUSFREQ too */ + intel_i2c_reset(dev); +} + +static int valleyview_cur_cdclk(struct drm_i915_private *dev_priv) +{ + int cur_cdclk, vco; + int divider; + + vco = valleyview_get_vco(dev_priv); + + mutex_lock(&dev_priv->dpio_lock); + divider = vlv_cck_read(dev_priv, 0x6b); + mutex_unlock(&dev_priv->dpio_lock); + + divider &= 0xf; + divider = ((divider + 1) * 10) / 2; + + cur_cdclk = (vco * 10) / divider; + + return cur_cdclk; +} + +static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv, + int max_pixclk) +{ + int cur_cdclk; + + cur_cdclk = valleyview_cur_cdclk(dev_priv); + + /* + * Really only a few cases to deal with, as only 4 CDclks are supported: + * 200MHz + * 267MHz + * 320MHz + * 400MHz + * So we check to see whether we're above 90% of the lower bin and + * adjust if needed. + */ + if (max_pixclk > 288000) { + return 400; + } else if (max_pixclk <= 288000 && max_pixclk > 240300) { + return 320; + } else + return 266; + /* Looks like the 200MHz CDclk freq doesn't work on some configs */ +} + +static int intel_mode_max_pixclk(struct drm_i915_private *dev_priv) +{ + struct drm_device *dev = dev_priv->dev; + struct intel_crtc *intel_crtc; + int max_pixclk = 0; + + list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, + base.head) { + if (!intel_crtc->base.enabled) + continue; + + if (max_pixclk < intel_crtc->config.adjusted_mode.clock) + max_pixclk = intel_crtc->config.adjusted_mode.clock; + } + + return max_pixclk; +} + +static void valleyview_modeset_global_pipes(struct drm_device *dev, + unsigned *prepare_pipes) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc; + int max_pixclk = intel_mode_max_pixclk(dev_priv); + int cur_cdclk = valleyview_cur_cdclk(dev_priv); + + if (valleyview_calc_cdclk(dev_priv, max_pixclk) == cur_cdclk) + return; + + list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, + base.head) + if (intel_crtc->base.enabled) + *prepare_pipes |= (1 << intel_crtc->pipe); +} + +static void valleyview_modeset_global_resources(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int max_pixclk = intel_mode_max_pixclk(dev_priv); + int cur_cdclk = valleyview_cur_cdclk(dev_priv); + int req_cdclk = valleyview_calc_cdclk(dev_priv, max_pixclk); + + if (req_cdclk != cur_cdclk) + valleyview_set_cdclk(dev, req_cdclk); +} + static void valleyview_crtc_enable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -10336,6 +10509,11 @@ static void intel_init_display(struct drm_device *dev) } } else if (IS_G4X(dev)) { dev_priv->display.write_eld = g4x_write_eld; + } else if (IS_VALLEYVIEW(dev)) { + dev_priv->display.modeset_global_resources = + valleyview_modeset_global_resources; + dev_priv->display.modeset_global_pipes = + valleyview_modeset_global_pipes; } /* Default just returns -ENODEV to indicate unsupported */ diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 2ca17b1..1263409 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -87,10 +87,6 @@ static void gmbus_set_freq(struct drm_i915_private *dev_priv) BUG_ON(!IS_VALLEYVIEW(dev_priv->dev)); - /* Skip setting the gmbus freq if BIOS has already programmed it */ - if (I915_READ(GMBUSFREQ_VLV) != 0xA0) - return; - /* Obtain SKU information */ mutex_lock(&dev_priv->dpio_lock); hpll_freq =