From: Pradeep Bhat <pradeep.b...@intel.com>

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 <pradeep.b...@intel.com>
Signed-off-by: Damien Lespiau <damien.lesp...@intel.com>
---
 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

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to