[PATCH 6.19 202/311] drm/i915/cdclk: Do the full CDCLK dance for min_voltage_level changes

Greg Kroah-Hartman
2026-04-08T18:58:30Z

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

commit e08e0754e690e4909cab83ac43fd2c93c6200514 upstream.

Apparently I forgot about the pipe min_voltage_level when I
decoupled the CDCLK calculations from modesets. Even if the
CDCLK frequency doesn't need changing we may still need to
bump the voltage level to accommodate an increase in the
port clock frequency.

Currently, even if there is a full modeset, we won't notice the
need to go through the full CDCLK calculations/programming,
unless the set of enabled/active pipes changes, or the
pipe/dbuf min CDCLK changes.

Duplicate the same logic we use the pipe's min CDCLK frequency
to also deal with its min voltage level.

Note that the 'allow_voltage_level_decrease' stuff isn't
really useful here since the min voltage level can only
change during a full modeset. But I think sticking to the
same approach in the three similar parts (pipe min cdclk,
pipe min voltage level, dbuf min cdclk) is a good idea.

Cc: stable@vger.kernel.org
Tested-by: Mikhail Rudenko <mike.rudenko@gmail.com>
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15826
Fixes: ba91b9eecb47 ("drm/i915/cdclk: Decouple cdclk from state->modeset")
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patch.msgid.link/20260325135849.12603-2-ville.syrjala@linux.intel.com
Reviewed-by: Michał Grzelak <michal.grzelak@intel.com>
(cherry picked from commit 0f21a14987ebae3c05ad1184ea872e7b7a7b8695)
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/i915/display/intel_cdclk.c | 54 +++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)

--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -2930,6 +2930,53 @@ static int intel_cdclk_update_crtc_min_c
return 0;
}

+static int intel_cdclk_update_crtc_min_voltage_level(struct intel_atomic_state *state,
+ struct intel_crtc *crtc,
+ u8 old_min_voltage_level,
+ u8 new_min_voltage_level,
+ bool *need_cdclk_calc)
+{
+ struct intel_display *display = to_intel_display(state);
+ struct intel_cdclk_state *cdclk_state;
+ bool allow_voltage_level_decrease = intel_any_crtc_needs_modeset(state);
+ int ret;
+
+ if (new_min_voltage_level == old_min_voltage_level)
+ return 0;
+
+ if (!allow_voltage_level_decrease &&
+ new_min_voltage_level < old_min_voltage_level)
+ return 0;
+
+ cdclk_state = intel_atomic_get_cdclk_state(state);
+ if (IS_ERR(cdclk_state))
+ return PTR_ERR(cdclk_state);
+
+ old_min_voltage_level = cdclk_state->min_voltage_level[crtc->pipe];
+
+ if (new_min_voltage_level == old_min_voltage_level)
+ return 0;
+
+ if (!allow_voltage_level_decrease &&
+ new_min_voltage_level < old_min_voltage_level)
+ return 0;
+
+ cdclk_state->min_voltage_level[crtc->pipe] = new_min_voltage_level;
+
+ ret = intel_atomic_lock_global_state(&cdclk_state->base);
+ if (ret)
+ return ret;
+
+ *need_cdclk_calc = true;
+
+ drm_dbg_kms(display->drm,
+ "[CRTC:%d:%s] min voltage level: %d -> %d\n",
+ crtc->base.base.id, crtc->base.name,
+ old_min_voltage_level, new_min_voltage_level);
+
+ return 0;
+}
+
int intel_cdclk_update_dbuf_bw_min_cdclk(struct intel_atomic_state *state,
int old_min_cdclk, int new_min_cdclk,
bool *need_cdclk_calc)
@@ -3345,6 +3392,13 @@ static int intel_crtcs_calc_min_cdclk(st
need_cdclk_calc);
if (ret)
return ret;
+
+ ret = intel_cdclk_update_crtc_min_voltage_level(state, crtc,
+ old_crtc_state->min_voltage_level,
+ new_crtc_state->min_voltage_level,
+ need_cdclk_calc);
+ if (ret)
+ return ret;
}

return 0;