This will make it easier to debug whether the hardware watermarks match what's calculated for intermediate and optimal watermarks. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/i915_debugfs.c | 153 ++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index c65e381b85f3..ac9ea47ac89f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -3170,6 +3170,158 @@ static void intel_scaler_info(struct seq_file *m, struct intel_crtc *intel_crtc) } } +static void intel_watermark_info(struct seq_file *m, + struct drm_i915_private *dev_priv, + struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + int i, j; + const char *names[3] = { + "hardware", + "intermediate", + "optimal" + }; + + if (INTEL_GEN(dev_priv) >= 9) { + struct skl_pipe_wm *wm = &crtc_state->wm.skl.optimal; + struct skl_ddb_entry *entry = &crtc_state->wm.skl.ddb; + struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb; + + seq_printf(m, "\tDDB allocation: start %u end %u, size %u\n", + entry->start, entry->end, skl_ddb_entry_size(entry)); + for (i = 0; i < ARRAY_SIZE(ddb->plane[crtc->pipe]); i++) { + entry = &ddb->plane[crtc->pipe][i]; + + if (!skl_ddb_entry_size(entry)) + continue; + + seq_printf(m, "\t\tplane %d%c DDB allocation: start %u end %u, size %u, ", + i, pipe_name(crtc->pipe), entry->start, entry->end, + skl_ddb_entry_size(entry)); + + entry = &ddb->y_plane[crtc->pipe][i]; + if (!skl_ddb_entry_size(entry)) + continue; + + seq_printf(m, "\t\tplane %d%c DDB Y allocation: start %u end %u, size %u, ", + i, pipe_name(crtc->pipe), entry->start, entry->end, + skl_ddb_entry_size(entry)); + } + + seq_printf(m, "\tLinetime: %u\n", wm->linetime); + + for (i = 0; i < ARRAY_SIZE(wm->planes); i++) { + struct skl_plane_wm *pwm = &wm->planes[i]; + + seq_printf(m, "\tplane %d%c, wm enabled: %s", + i, pipe_name(crtc->pipe), + enableddisabled(pwm->wm[0].plane_en)); + if (!pwm->wm[0].plane_en) + continue; + + seq_printf(m, "\t\tTransition wm: %s, lines %u, blocks %u", + enableddisabled(pwm->trans_wm.plane_en), + pwm->trans_wm.plane_res_b, pwm->trans_wm.plane_res_l); + + for (j = 0; j < ARRAY_SIZE(pwm->wm); j++) { + if (!pwm->wm[j].plane_en) + break; + + seq_printf(m, "\t\tLevel[%u]: lines %u, blocks %u", + j, pwm->trans_wm.plane_res_b, + pwm->trans_wm.plane_res_l); + } + } + } else if (HAS_PCH_SPLIT(dev_priv)) { + struct intel_pipe_wm *wm; + struct intel_pipe_wm *wms[3] = { + &crtc->wm.active.ilk, + &crtc_state->wm.ilk.intermediate, + &crtc_state->wm.ilk.optimal }; + + for (j = 0, wm = *wms; j < 3; j++, wm = wms[j]) { + seq_printf(m, "\tDumping %s watermarks, post vbl update: %s\n", + names[j], yesno(crtc_state->wm.need_postvbl_update)); + + for (i = 0; i < ARRAY_SIZE(wm->wm); i++) { + struct intel_wm_level *lvl = &wm->wm[i]; + + seq_printf(m, "\t\twm level[%i], enabled: %s, vals: %u, %u, %u, %u\n", + i, yesno(lvl->enable), lvl->pri_val, + lvl->spr_val, lvl->cur_val, lvl->fbc_val); + } + + seq_printf(m, "\tLinetime: %u\n", wm->linetime); + seq_printf(m, "\tfbc wm enabled: %s, pipe: %s, sprites enabled: %s, scaled: %s\n", + yesno(wm->fbc_wm_enabled), yesno(wm->pipe_enabled), + yesno(wm->sprites_enabled), yesno(wm->sprites_scaled)); + } + } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + struct vlv_wm_state *wm; + struct vlv_wm_state *wms[3] = { + &crtc->wm.active.vlv, + &crtc_state->wm.vlv.intermediate, + &crtc_state->wm.vlv.optimal }; + + for (j = 0, wm = *wms; j < 3; j++, wm = wms[j]) { + seq_printf(m, "\tDumping %s watermarks, CxSR: %s, num levels: %u\n", + names[j], yesno(wm->cxsr), wm->num_levels); + + for (i = 0; i < wm->num_levels; i++) { + struct g4x_pipe_wm *pwm = &wm->wm[i]; + struct g4x_sr_wm *sr = &wm->sr[i]; + int k; + + seq_printf(m, "\tLevel %u allocations:\n", i); + for (k = 0; k < ARRAY_SIZE(pwm->plane); k++) + seq_printf(m, "\t\tPlane %u: %u\n", k, pwm->plane[k]); + seq_printf(m, "\t\tFBC: %u\n", pwm->fbc); + + if (!wm->cxsr) + continue; + + seq_printf(m, "\t\tSR: plane %u, cursor %u, FBC %u\n", + sr->plane, sr->cursor, sr->fbc); + } + } + } else if (IS_G4X(dev_priv)) { + struct g4x_wm_state *wm; + struct g4x_wm_state *wms[3] = { + &crtc->wm.active.g4x, + &crtc_state->wm.g4x.intermediate, + &crtc_state->wm.g4x.optimal }; + + for (j = 0, wm = *wms; j < 3; j++, wm = wms[j]) { + struct g4x_pipe_wm *pwm = &wm->wm; + struct g4x_sr_wm *sr = &wm->sr; + struct g4x_sr_wm *hpll = &wm->hpll; + + seq_printf(m, "\tDumping %s watermarks, CxSR: %s, HPLL: %s, fbc: %s\n", + names[j], yesno(wm->cxsr), yesno(wm->hpll_en), + yesno(wm->fbc_en)); + + for (i = 0; i < ARRAY_SIZE(pwm->plane); i++) + seq_printf(m, "\t\tPlane %u: %u\n", i, pwm->plane[i]); + + if (wm->fbc_en) + seq_printf(m, "\t\tFBC: %u\n", pwm->fbc); + + if (wm->cxsr) + seq_printf(m, "\t\tSR: plane %u, cursor %u, FBC %u\n", + sr->plane, sr->cursor, sr->fbc); + + if (wm->hpll_en) + seq_printf(m, "\t\tHPLL: plane %u, cursor %u, FBC %u\n", + hpll->plane, hpll->cursor, hpll->fbc); + } + } + + if (dev_priv->display.optimize_watermarks) + seq_printf(m, "\tNeed post vblank update: %s\n", + yesno(crtc_state->wm.need_postvbl_update)); +} + static int i915_display_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -3208,6 +3360,7 @@ static int i915_display_info(struct seq_file *m, void *unused) cursor->cursor.base); intel_scaler_info(m, crtc); intel_plane_info(m, crtc); + intel_watermark_info(m, dev_priv, crtc); } seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s \n", -- 2.14.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx