Commit e08e0754 authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Joonas Lahtinen
Browse files

drm/i915/cdclk: Do the full CDCLK dance for min_voltage_level changes



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: default avatarMikhail Rudenko <mike.rudenko@gmail.com>
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/15826


Fixes: ba91b9ee ("drm/i915/cdclk: Decouple cdclk from state->modeset")
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patch.msgid.link/20260325135849.12603-2-ville.syrjala@linux.intel.com


Reviewed-by: default avatarMichał Grzelak <michal.grzelak@intel.com>
(cherry picked from commit 0f21a14987ebae3c05ad1184ea872e7b7a7b8695)
Signed-off-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
parent 4dfce79e
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
@@ -2971,6 +2971,53 @@ static int intel_cdclk_update_crtc_min_cdclk(struct intel_atomic_state *state,
	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)
@@ -3386,6 +3433,13 @@ static int intel_crtcs_calc_min_cdclk(struct intel_atomic_state *state,
							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;