From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> In order to simplify the code let's store all memory latency values in 0.1 usec units. This limits the platform specific units to the initial setup code for the most part. v2: Write the constants as '<usec> * 10' for clarity Fix up the SKL+ wm calculations to match the .1 usec latency units Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/i915_debugfs.c | 12 -- drivers/gpu/drm/i915/i915_drv.h | 14 +-- drivers/gpu/drm/i915/intel_pm.c | 166 ++++++++++++++++------------ 3 files changed, 95 insertions(+), 97 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5cadfcd03ea9..189402f7164f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3806,18 +3806,6 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8]) for (level = 0; level < num_levels; level++) { unsigned int latency = wm[level]; - /* - * - WM1+ latency values in 0.5us units - * - latencies are in us on gen9/vlv/chv - */ - if (INTEL_GEN(dev_priv) >= 9 || - IS_VALLEYVIEW(dev_priv) || - IS_CHERRYVIEW(dev_priv) || - IS_G4X(dev_priv)) - latency *= 10; - else if (level > 0) - latency *= 5; - seq_printf(m, "WM%d %u (%u.%u usec)\n", level, wm[level], latency / 10, latency % 10); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2d7761b8ac07..2c6141590f2f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1888,22 +1888,10 @@ struct drm_i915_private { } sagv_status; struct { - /* - * Raw watermark latency values: - * in 0.1us units for WM0, - * in 0.5us units for WM1+. - */ - /* primary */ + /* Watermark memory latency values in 0.1 us units */ uint16_t pri_latency[5]; - /* sprite */ 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 */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 688298cf1aaf..bdd47f74fc74 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -801,6 +801,27 @@ static int intel_wm_num_levels(struct drm_i915_private *dev_priv) return dev_priv->wm.max_level + 1; } +static int intel_plane_wm_latency(struct intel_plane *plane, + int level) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + + if (INTEL_GEN(dev_priv) >= 9) + return dev_priv->wm.skl_latency[level]; + + if (HAS_GMCH_DISPLAY(dev_priv)) + return dev_priv->wm.pri_latency[level]; + + switch (plane->id) { + case PLANE_PRIMARY: + return dev_priv->wm.pri_latency[level]; + case PLANE_CURSOR: + return dev_priv->wm.cur_latency[level]; + default: + return dev_priv->wm.spr_latency[level]; + } +} + static bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { @@ -1039,10 +1060,10 @@ static void vlv_write_wm_values(struct drm_i915_private *dev_priv, static void g4x_setup_wm_latency(struct drm_i915_private *dev_priv) { - /* all latencies in usec */ - dev_priv->wm.pri_latency[G4X_WM_LEVEL_NORMAL] = 5; - dev_priv->wm.pri_latency[G4X_WM_LEVEL_SR] = 12; - dev_priv->wm.pri_latency[G4X_WM_LEVEL_HPLL] = 35; + /* all latencies in .1 usec */ + dev_priv->wm.pri_latency[G4X_WM_LEVEL_NORMAL] = 5 * 10; + dev_priv->wm.pri_latency[G4X_WM_LEVEL_SR] = 12 * 10; + dev_priv->wm.pri_latency[G4X_WM_LEVEL_HPLL] = 35 * 10; dev_priv->wm.max_level = G4X_WM_LEVEL_HPLL; } @@ -1097,7 +1118,7 @@ static uint16_t g4x_compute_wm(const struct intel_crtc_state *crtc_state, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; - unsigned int latency = dev_priv->wm.pri_latency[level] * 10; + int latency = intel_plane_wm_latency(plane, level); unsigned int clock, htotal, cpp, width, wm; if (latency == 0) @@ -1586,14 +1607,14 @@ static unsigned int vlv_wm_method2(unsigned int pixel_rate, static void vlv_setup_wm_latency(struct drm_i915_private *dev_priv) { - /* all latencies in usec */ - dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM2] = 3; + /* all latencies in .1 usec */ + dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM2] = 3 * 10; dev_priv->wm.max_level = VLV_WM_LEVEL_PM2; if (IS_CHERRYVIEW(dev_priv)) { - dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM5] = 12; - dev_priv->wm.pri_latency[VLV_WM_LEVEL_DDR_DVFS] = 33; + dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM5] = 12 * 10; + dev_priv->wm.pri_latency[VLV_WM_LEVEL_DDR_DVFS] = 33 * 10; dev_priv->wm.max_level = VLV_WM_LEVEL_DDR_DVFS; } @@ -1604,12 +1625,12 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, int level) { struct intel_plane *plane = to_intel_plane(plane_state->base.plane); - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; + int latency = intel_plane_wm_latency(plane, level); unsigned int clock, htotal, cpp, width, wm; - if (dev_priv->wm.pri_latency[level] == 0) + if (latency == 0) return USHRT_MAX; if (!intel_wm_plane_visible(crtc_state, plane_state)) @@ -1629,8 +1650,7 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state, */ wm = 63; } else { - wm = vlv_wm_method2(clock, htotal, width, cpp, - dev_priv->wm.pri_latency[level] * 10); + wm = vlv_wm_method2(clock, htotal, width, cpp, latency); } return min_t(unsigned int, wm, USHRT_MAX); @@ -2481,15 +2501,12 @@ struct ilk_wm_maximums { uint16_t fbc; }; -/* - * For both WM_PIPE and WM_LP. - * mem_value must be in 0.1us units. - */ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate, const struct intel_plane_state *pstate, - uint32_t mem_value, - bool is_lp) + int level) { + struct intel_plane *plane = to_intel_plane(pstate->base.plane); + int latency = intel_plane_wm_latency(plane, level); uint32_t method1, method2; int cpp; @@ -2498,27 +2515,25 @@ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate, cpp = pstate->base.fb->format->cpp[0]; - method1 = ilk_wm_method1(cstate->pixel_rate, cpp, mem_value); + method1 = ilk_wm_method1(cstate->pixel_rate, cpp, latency); - if (!is_lp) + if (level == 0) return method1; method2 = ilk_wm_method2(cstate->pixel_rate, cstate->base.adjusted_mode.crtc_htotal, drm_rect_width(&pstate->base.dst), - cpp, mem_value); + cpp, latency); return min(method1, method2); } -/* - * For both WM_PIPE and WM_LP. - * mem_value must be in 0.1us units. - */ static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate, const struct intel_plane_state *pstate, - uint32_t mem_value) + int level) { + struct intel_plane *plane = to_intel_plane(pstate->base.plane); + int latency = intel_plane_wm_latency(plane, level); uint32_t method1, method2; int cpp; @@ -2527,22 +2542,20 @@ static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate, cpp = pstate->base.fb->format->cpp[0]; - method1 = ilk_wm_method1(cstate->pixel_rate, cpp, mem_value); + method1 = ilk_wm_method1(cstate->pixel_rate, cpp, latency); method2 = ilk_wm_method2(cstate->pixel_rate, cstate->base.adjusted_mode.crtc_htotal, drm_rect_width(&pstate->base.dst), - cpp, mem_value); + cpp, latency); return min(method1, method2); } -/* - * For both WM_PIPE and WM_LP. - * mem_value must be in 0.1us units. - */ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate, const struct intel_plane_state *pstate, - uint32_t mem_value) + int level) { + struct intel_plane *plane = to_intel_plane(pstate->base.plane); + int latency = intel_plane_wm_latency(plane, level); int cpp; if (!intel_wm_plane_visible(cstate, pstate)) @@ -2552,7 +2565,7 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate, return ilk_wm_method2(cstate->pixel_rate, cstate->base.adjusted_mode.crtc_htotal, - pstate->base.crtc_w, cpp, mem_value); + pstate->base.crtc_w, cpp, latency); } /* Only for WM_LP. */ @@ -2743,28 +2756,16 @@ static void ilk_compute_wm_level(const struct drm_i915_private *dev_priv, const struct intel_plane_state *curstate, struct intel_wm_level *result) { - uint16_t pri_latency = dev_priv->wm.pri_latency[level]; - uint16_t spr_latency = dev_priv->wm.spr_latency[level]; - uint16_t cur_latency = dev_priv->wm.cur_latency[level]; - - /* WM1+ latency values stored in 0.5us units */ - if (level > 0) { - pri_latency *= 5; - spr_latency *= 5; - cur_latency *= 5; - } - if (pristate) { - result->pri_val = ilk_compute_pri_wm(cstate, pristate, - pri_latency, level); + result->pri_val = ilk_compute_pri_wm(cstate, pristate, level); result->fbc_val = ilk_compute_fbc_wm(cstate, pristate, result->pri_val); } if (sprstate) - result->spr_val = ilk_compute_spr_wm(cstate, sprstate, spr_latency); + result->spr_val = ilk_compute_spr_wm(cstate, sprstate, level); if (curstate) - result->cur_val = ilk_compute_cur_wm(cstate, curstate, cur_latency); + result->cur_val = ilk_compute_cur_wm(cstate, curstate, level); result->enable = true; } @@ -2929,6 +2930,16 @@ static void intel_fixup_cur_wm_latency(struct drm_i915_private *dev_priv, wm[0] = 13; } +static void ilk_fixup_wm_latency_units(struct drm_i915_private *dev_priv, + u16 wm[5]) +{ + int level, num_levels = ilk_wm_max_level(dev_priv) + 1; + + /* convert .5 usec to .1 usec units */ + for (level = 1; level < num_levels; level++) + wm[level] *= 5; +} + int ilk_wm_max_level(const struct drm_i915_private *dev_priv) { /* how many WM levels are we expecting */ @@ -2957,15 +2968,6 @@ static void intel_print_wm_latency(struct drm_i915_private *dev_priv, continue; } - /* - * - latencies are in us on gen9. - * - before then, WM1+ latency values are in 0.5us units - */ - if (INTEL_GEN(dev_priv) >= 9) - latency *= 10; - else if (level > 0) - latency *= 5; - DRM_DEBUG_KMS("%s WM%d latency %u (%u.%u usec)\n", name, level, wm[level], latency / 10, latency % 10); @@ -2973,16 +2975,19 @@ static void intel_print_wm_latency(struct drm_i915_private *dev_priv, } static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv, - uint16_t wm[5], uint16_t min) + u16 wm[5], u16 min) { int level, max_level = ilk_wm_max_level(dev_priv); if (wm[0] >= min) return false; - wm[0] = max(wm[0], min); + wm[0] = min; + + /* WM1+ latencies must be multiples of .5 usec */ + min = roundup(min, 5); for (level = 1; level <= max_level; level++) - wm[level] = max_t(uint16_t, wm[level], DIV_ROUND_UP(min, 5)); + wm[level] = max(wm[level], min); return true; } @@ -3012,6 +3017,8 @@ static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv) { intel_read_wm_latency(dev_priv, dev_priv->wm.pri_latency); + ilk_fixup_wm_latency_units(dev_priv, dev_priv->wm.pri_latency); + memcpy(dev_priv->wm.spr_latency, dev_priv->wm.pri_latency, sizeof(dev_priv->wm.pri_latency)); memcpy(dev_priv->wm.cur_latency, dev_priv->wm.pri_latency, @@ -3028,9 +3035,22 @@ static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv) snb_wm_latency_quirk(dev_priv); } +static void skl_fixup_wm_latency_units(struct drm_i915_private *dev_priv, + u16 wm[8]) +{ + int level, num_levels = ilk_wm_max_level(dev_priv) + 1; + + /* convert usec to .1 usec units */ + for (level = 0; level < num_levels; level++) + wm[level] *= 10; +} + static void skl_setup_wm_latency(struct drm_i915_private *dev_priv) { intel_read_wm_latency(dev_priv, dev_priv->wm.skl_latency); + + skl_fixup_wm_latency_units(dev_priv, dev_priv->wm.skl_latency); + intel_print_wm_latency(dev_priv, "Gen9 Plane", dev_priv->wm.skl_latency); } @@ -3302,7 +3322,8 @@ static unsigned int ilk_wm_lp_latency(struct drm_device *dev, int level) if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) return 2 * level; else - return dev_priv->wm.pri_latency[level]; + /* specified in .5 usec units */ + return dev_priv->wm.pri_latency[level] / 5; } static void ilk_compute_wm_results(struct drm_device *dev, @@ -3762,19 +3783,19 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state) !wm->wm[level].plane_en; --level) { } - latency = dev_priv->wm.skl_latency[level]; + latency = intel_plane_wm_latency(plane, level); if (skl_needs_memory_bw_wa(intel_state) && plane->base.state->fb->modifier == I915_FORMAT_MOD_X_TILED) - latency += 15; + latency += 15 * 10; /* * If any of the planes on this pipe don't enable wm levels that * incur memory latencies higher than sagv_block_time_us we * can't enable the SAGV. */ - if (latency < sagv_block_time_us) + if (latency < sagv_block_time_us * 10) return false; } @@ -4514,7 +4535,7 @@ skl_wm_method1(const struct drm_i915_private *dev_priv, uint32_t pixel_rate, return FP_16_16_MAX; wm_intermediate_val = latency * pixel_rate * cpp; - ret = div_fixed16(wm_intermediate_val, 1000 * dbuf_block_size); + ret = div_fixed16(wm_intermediate_val, 10000 * dbuf_block_size); if (INTEL_GEN(dev_priv) >= 10) ret = add_fixed16_u32(ret, 1); @@ -4535,7 +4556,7 @@ static uint_fixed_16_16_t skl_wm_method2(uint32_t pixel_rate, wm_intermediate_val = latency * pixel_rate; wm_intermediate_val = DIV_ROUND_UP(wm_intermediate_val, - pipe_htotal * 1000); + pipe_htotal * 10000); ret = mul_u32_fixed16(wm_intermediate_val, plane_blocks_per_line); return ret; } @@ -4701,7 +4722,8 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, struct skl_wm_level *result /* out */) { const struct drm_plane_state *pstate = &intel_pstate->base; - uint32_t latency = dev_priv->wm.skl_latency[level]; + uint32_t latency = intel_plane_wm_latency(to_intel_plane(pstate->plane), + level); uint_fixed_16_16_t method1, method2; uint_fixed_16_16_t selected_result; uint32_t res_blocks, res_lines; @@ -4720,10 +4742,10 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv) || IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_B0)) && dev_priv->ipc_enabled) - latency += 4; + latency += 4 * 10; if (apply_memory_bw_wa && wp->x_tiled) - latency += 15; + latency += 15 * 10; method1 = skl_wm_method1(dev_priv, wp->plane_pixel_rate, wp->cpp, latency, wp->dbuf_block_size); @@ -4746,7 +4768,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, selected_result = min_fixed16(method1, method2); else selected_result = method2; - } else if (latency >= wp->linetime_us) { + } else if (latency >= wp->linetime_us * 10) { if (INTEL_GEN(dev_priv) == 9 && !IS_GEMINILAKE(dev_priv)) selected_result = min_fixed16(method1, method2); -- 2.18.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx