Commit 3aecee90 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915/cdclk: Fix CDCLK programming order when pipes are active

Currently we always reprogram CDCLK from the
intel_set_cdclk_pre_plane_update() when using squash/crawl.
The code only works correctly for the cd2x update or full
modeset cases, and it was simply never updated to deal with
squash/crawl.

If the CDCLK frequency is increasing we must reprogram it
before we do anything else that might depend on the new
higher frequency, and conversely we must not decrease
the frequency until everything that might still depend
on the old higher frequency has been dealt with.

Since cdclk_state->pipe is only relevant when doing a cd2x
update we can't use it to determine the correct sequence
during squash/crawl. To that end introduce cdclk_state->disable_pipes
which simply indicates that we must perform the update
while the pipes are disable (ie. during
intel_set_cdclk_pre_plane_update()). Otherwise we use the
same old vs. new CDCLK frequency comparsiong as for cd2x
updates.

The only remaining problem case is when the voltage_level
needs to increase due to a DDI port, but the CDCLK frequency
is decreasing (and not all pipes are being disabled). The
current approach will not bump the voltage level up until
after the port has already been enabled, which is too late.
But we'll take care of that case separately.

v2: Don't break the "must disable pipes case"
v3: Keep the on stack 'pipe' for future use

Cc: stable@vger.kernel.org
Fixes: d62686ba ("drm/i915/adl_p: CDCLK crawl support for ADL")
Reviewed-by: default avatarUma Shankar <uma.shankar@intel.com>
Reviewed-by: default avatarGustavo Sousa <gustavo.sousa@intel.com>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240402155016.13733-2-ville.syrjala@linux.intel.com
parent 8845021b
...@@ -2609,7 +2609,7 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state) ...@@ -2609,7 +2609,7 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
if (IS_DG2(i915)) if (IS_DG2(i915))
intel_cdclk_pcode_pre_notify(state); intel_cdclk_pcode_pre_notify(state);
if (pipe == INVALID_PIPE || if (new_cdclk_state->disable_pipes ||
old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) { old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) {
drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
...@@ -2641,7 +2641,7 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state) ...@@ -2641,7 +2641,7 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
if (IS_DG2(i915)) if (IS_DG2(i915))
intel_cdclk_pcode_post_notify(state); intel_cdclk_pcode_post_notify(state);
if (pipe != INVALID_PIPE && if (!new_cdclk_state->disable_pipes &&
old_cdclk_state->actual.cdclk > new_cdclk_state->actual.cdclk) { old_cdclk_state->actual.cdclk > new_cdclk_state->actual.cdclk) {
drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
...@@ -3124,6 +3124,7 @@ static struct intel_global_state *intel_cdclk_duplicate_state(struct intel_globa ...@@ -3124,6 +3124,7 @@ static struct intel_global_state *intel_cdclk_duplicate_state(struct intel_globa
return NULL; return NULL;
cdclk_state->pipe = INVALID_PIPE; cdclk_state->pipe = INVALID_PIPE;
cdclk_state->disable_pipes = false;
return &cdclk_state->base; return &cdclk_state->base;
} }
...@@ -3316,6 +3317,8 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) ...@@ -3316,6 +3317,8 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
if (ret) if (ret)
return ret; return ret;
new_cdclk_state->disable_pipes = true;
drm_dbg_kms(&dev_priv->drm, drm_dbg_kms(&dev_priv->drm,
"Modeset required for cdclk change\n"); "Modeset required for cdclk change\n");
} }
......
...@@ -53,6 +53,9 @@ struct intel_cdclk_state { ...@@ -53,6 +53,9 @@ struct intel_cdclk_state {
/* bitmask of active pipes */ /* bitmask of active pipes */
u8 active_pipes; u8 active_pipes;
/* update cdclk with pipes disabled */
bool disable_pipes;
}; };
int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state); int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment