From mboxrd@z Thu Jan 1 00:00:00 1970 From: Damien Lespiau Subject: [PATCH 43/89] drm/i915/skl: Read the Memory Latency Values for WM computation Date: Thu, 4 Sep 2014 12:27:09 +0100 Message-ID: <1409830075-11139-44-git-send-email-damien.lespiau@intel.com> References: <1409830075-11139-1-git-send-email-damien.lespiau@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by gabe.freedesktop.org (Postfix) with ESMTP id 58B716E67F for ; Thu, 4 Sep 2014 04:28:37 -0700 (PDT) In-Reply-To: <1409830075-11139-1-git-send-email-damien.lespiau@intel.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To: intel-gfx@lists.freedesktop.org Cc: Pradeep Bhat List-Id: intel-gfx@lists.freedesktop.org From: Pradeep Bhat This patch reads the memory latency values for all the 8 levels for SKL. These values are needed for the Watermark computation. v2: Incorporated the review comments from Damien on register indentation. v3: Updated the code to use the sandybridge_pcode_read for reading memory latencies for GEN9. v4: Don't put gen 9 in the middle of an ordered list of ifs (Damien) v5 take the rps.hw_lock around sandybridge_pcode_read() (Damien) Signed-off-by: Pradeep Bhat Signed-off-by: Damien Lespiau --- drivers/gpu/drm/i915/i915_drv.h | 6 ++++ drivers/gpu/drm/i915/i915_reg.h | 9 +++++ drivers/gpu/drm/i915/intel_pm.c | 73 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 82 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index dcd1c72..32be299 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1665,6 +1665,12 @@ struct drm_i915_private { uint16_t spr_latency[5]; /* cursor */ uint16_t cur_latency[5]; + /* + * Raw watermark memory latency values + * for SKL for all 8 levels + * in 1us units. + */ + uint16_t skl_latency[8]; /* current hardware state */ struct ilk_wm_values hw; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0159f2d..bc55990 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2018,6 +2018,15 @@ enum punit_power_well { #define MAD_DIMM_A_SIZE_SHIFT 0 #define MAD_DIMM_A_SIZE_MASK (0xff << MAD_DIMM_A_SIZE_SHIFT) +/* SKL GT Driver Mailbox registers for reading memory latencies */ +#define GEN9_MAILBOX_DATA1 0x13812C +#define GEN9_MAILBOX_READ_MEM_LAT (0x6) +#define GEN9_MAILBOX_READ_TIMEOUT 150 +#define GEN9_MEM_LAT_LEVEL_MASK 0xFF +#define GEN9_MEM_LAT_LEVEL_1_5_SHIFT 8 +#define GEN9_MEM_LAT_LEVEL_2_6_SHIFT 16 +#define GEN9_MEM_LAT_LEVEL_3_7_SHIFT 24 + /* snb MCH registers for priority tuning */ #define MCH_SSKPD (MCHBAR_MIRROR_BASE_SNB + 0x5d10) #define MCH_SSKPD_WM0_MASK 0x3f diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a236e77..d8c8531 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2239,11 +2239,53 @@ hsw_compute_linetime_wm(struct drm_device *dev, struct drm_crtc *crtc) PIPE_WM_LINETIME_TIME(linetime); } -static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[5]) +static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8]) { struct drm_i915_private *dev_priv = dev->dev_private; - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { + if (IS_GEN9(dev)) { + uint32_t val; + int ret; + + /* read the first set of memory latencies[0:3] */ + val = 0; /* data0 to be programmed to 0 for first set */ + mutex_lock(&dev_priv->rps.hw_lock); + ret = sandybridge_pcode_read(dev_priv, + GEN9_MAILBOX_READ_MEM_LAT, + &val); + mutex_unlock(&dev_priv->rps.hw_lock); + + if (ret) { + DRM_ERROR("SKL Mailbox read error = %d\n", ret); + return; + } + wm[0] = val & GEN9_MEM_LAT_LEVEL_MASK; + wm[1] = (val >> GEN9_MEM_LAT_LEVEL_1_5_SHIFT) & + GEN9_MEM_LAT_LEVEL_MASK; + wm[2] = (val >> GEN9_MEM_LAT_LEVEL_2_6_SHIFT) & + GEN9_MEM_LAT_LEVEL_MASK; + wm[3] = (val >> GEN9_MEM_LAT_LEVEL_3_7_SHIFT) & + GEN9_MEM_LAT_LEVEL_MASK; + + /* read the second set of memory latencies[4:7] */ + val = 1; /* data0 to be programmed to 1 for second set */ + mutex_lock(&dev_priv->rps.hw_lock); + ret = sandybridge_pcode_read(dev_priv, + GEN9_MAILBOX_READ_MEM_LAT, + &val); + mutex_unlock(&dev_priv->rps.hw_lock); + if (ret) { + DRM_ERROR("SKL Mailbox read error = %d\n", ret); + return; + } + wm[4] = val & GEN9_MEM_LAT_LEVEL_MASK; + wm[5] = (val >> GEN9_MEM_LAT_LEVEL_1_5_SHIFT) & + GEN9_MEM_LAT_LEVEL_MASK; + wm[6] = (val >> GEN9_MEM_LAT_LEVEL_2_6_SHIFT) & + GEN9_MEM_LAT_LEVEL_MASK; + wm[7] = (val >> GEN9_MEM_LAT_LEVEL_3_7_SHIFT) & + GEN9_MEM_LAT_LEVEL_MASK; + } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { uint64_t sskpd = I915_READ64(MCH_SSKPD); wm[0] = (sskpd >> 56) & 0xFF; @@ -2291,7 +2333,9 @@ static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5]) int ilk_wm_max_level(const struct drm_device *dev) { /* how many WM levels are we expecting */ - if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + if (IS_GEN9(dev)) + return 7; + else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) return 4; else if (INTEL_INFO(dev)->gen >= 6) return 3; @@ -2300,7 +2344,7 @@ int ilk_wm_max_level(const struct drm_device *dev) } static void intel_print_wm_latency(struct drm_device *dev, const char *name, - const uint16_t wm[5]) + const uint16_t wm[8]) { int level, max_level = ilk_wm_max_level(dev); @@ -2313,8 +2357,13 @@ static void intel_print_wm_latency(struct drm_device *dev, continue; } - /* WM1+ latency values in 0.5us units */ - if (level > 0) + /* + * - latencies are in us on gen9. + * - before then, WM1+ latency values are in 0.5us units + */ + if (IS_GEN9(dev)) + latency *= 10; + else if (level > 0) latency *= 5; DRM_DEBUG_KMS("%s WM%d latency %u (%u.%u usec)\n", @@ -2382,6 +2431,14 @@ static void ilk_setup_wm_latency(struct drm_device *dev) snb_wm_latency_quirk(dev); } +static void skl_setup_wm_latency(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + intel_read_wm_latency(dev, dev_priv->wm.skl_latency); + intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency); +} + static void ilk_compute_wm_parameters(struct drm_crtc *crtc, struct ilk_pipe_wm_parameters *p) { @@ -7396,6 +7453,8 @@ void intel_init_pm(struct drm_device *dev) /* For FIFO watermark updates */ if (IS_GEN9(dev)) { + skl_setup_wm_latency(dev); + dev_priv->display.init_clock_gating = gen9_init_clock_gating; } else if (HAS_PCH_SPLIT(dev)) { ilk_setup_wm_latency(dev); @@ -7488,6 +7547,8 @@ int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val) } I915_WRITE(GEN6_PCODE_DATA, *val); + if (IS_GEN9(dev_priv->dev)) + I915_WRITE(GEN9_MAILBOX_DATA1, 0); I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY | mbox); if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, -- 1.8.3.1