From: Ville Syrjälä <[email protected]> Adjust intel_cdclk_prefill_adjustment() to give out a potentially more optimal value, purely based on the final minimum CDCLK (also considering planes/pfit/etc.) for the current pipe. We can't actually check against the current CDCLK frequency as that might be much higher due to some other pipe, and said other pipe might later reduce the CDCLK below what the current pipe would find acceptable (given which WM levels are enabled). Ie. we don't consider any global constraints (other pipes, dbuf bandwidth, etc) on the mimimum CDCLK frequency here.
We must also make sure crtc_state->min_cdclk doesn't exceed the platform max or else _intel_cdclk_prefill_adj() will get confused when trying to find the corresponding platform specific cdclk frequency. v2: check min_cdclk against platform max Reviewed-by: Luca Coelho <[email protected]> #v1 Signed-off-by: Ville Syrjälä <[email protected]> --- drivers/gpu/drm/i915/display/intel_cdclk.c | 17 +++++++++++++++-- drivers/gpu/drm/i915/display/intel_display.c | 6 ++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index e92e7fd9fd13..838834c49a90 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -4092,8 +4092,21 @@ static unsigned int _intel_cdclk_prefill_adj(const struct intel_crtc_state *crtc unsigned int intel_cdclk_prefill_adjustment(const struct intel_crtc_state *crtc_state) { - /* FIXME use the actual min_cdclk for the pipe here */ - return intel_cdclk_prefill_adjustment_worst(crtc_state); + int clock = crtc_state->hw.pipe_mode.crtc_clock; + int min_cdclk; + + /* + * Only consider the current pipe's minimum cdclk here as a safe + * lower bound. This must *not* be based on the actual/logical cdclk + * frequency here as that may get reduced later due to eg. a modeset + * on a different pipe, and that would completely invalidate the + * guardband length checks we did on this pipe previously. That + * could lead to prefill exceeding the guardband which would result + * in underruns. + */ + min_cdclk = crtc_state->min_cdclk; + + return _intel_cdclk_prefill_adj(crtc_state, clock, min_cdclk); } unsigned int intel_cdclk_prefill_adjustment_worst(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2eb714fbc35f..0ce6f923d722 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5759,6 +5759,12 @@ static int intel_atomic_check_crtcs(struct intel_atomic_state *state) int ret; new_crtc_state->min_cdclk = intel_crtc_min_cdclk(new_crtc_state); + if (new_crtc_state->min_cdclk > display->cdclk.max_cdclk_freq) { + drm_dbg_kms(display->drm, "[CRTC:%d:%s] required cdclk (%d kHz) exceeds max (%d kHz)\n", + crtc->base.base.id, crtc->base.name, new_crtc_state->min_cdclk, + display->cdclk.max_cdclk_freq); + return -EINVAL; + } if (DISPLAY_VER(display) >= 9) { ret = intel_atomic_setup_scalers(state, crtc); -- 2.49.1
