@@ -39,6 +39,7 @@
#include "intel_pcode.h"
#include "intel_psr.h"
#include "intel_vdsc.h"
+#include "skl_watermark.h"
#include "vlv_sideband.h"
/**
@@ -1800,6 +1801,16 @@ static bool cdclk_pll_is_unknown(unsigned int vco)
return vco == ~0;
}
+/* Return the MBUS_CTL's encoding of the mdclk/cdclk ratio */
+static int get_mdclk_cdclk_ratio(struct drm_i915_private *i915,
+ const struct intel_cdclk_config *cdclk_config)
+{
+ if (DISPLAY_VER(i915) >= 20)
+ return DIV_ROUND_UP(cdclk_config->vco, cdclk_config->cdclk) - 1;
+
+ return 1;
+}
+
static int cdclk_squash_divider(u16 waveform)
{
return hweight16(waveform ?: 0xffff);
@@ -2712,6 +2723,8 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
struct intel_crtc_state *crtc_state;
int min_cdclk, i;
enum pipe pipe;
+ struct intel_dbuf_state *new_dbuf_state;
+ struct intel_dbuf_state *old_dbuf_state;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
int ret;
@@ -2745,6 +2758,21 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state)
}
}
+ new_dbuf_state = intel_atomic_get_new_dbuf_state(state);
+ old_dbuf_state = intel_atomic_get_old_dbuf_state(state);
+ if (new_dbuf_state && old_dbuf_state) {
+ new_dbuf_state->mdclk_cdclk_ratio =
+ get_mdclk_cdclk_ratio(dev_priv, &cdclk_state->actual);
+
+ if (new_dbuf_state->mdclk_cdclk_ratio != old_dbuf_state->mdclk_cdclk_ratio) {
+ int ret;
+
+ ret = intel_atomic_serialize_global_state(&new_dbuf_state->base);
+ if (ret)
+ return ret;
+ }
+ }
+
min_cdclk = max(cdclk_state->force_min_cdclk,
cdclk_state->bw_min_cdclk);
for_each_pipe(dev_priv, pipe)
@@ -3472,6 +3472,16 @@ int intel_dbuf_init(struct drm_i915_private *i915)
return 0;
}
+static int get_mbus_mdclk_cdclk_ratio(struct drm_i915_private *i915,
+ int mdclk_cdclk_ratio,
+ int mbus_joined)
+{
+ if (mbus_joined)
+ return (mdclk_cdclk_ratio << 1) + 1;
+
+ return mdclk_cdclk_ratio;
+}
+
/*
* Configure MBUS_CTL and all DBUF_CTL_S of each slice to join_mbus state before
* update the request state of all DBUS slices.
@@ -3483,10 +3493,16 @@ static void update_mbus_pre_enable(struct intel_atomic_state *state)
enum dbuf_slice slice;
const struct intel_dbuf_state *dbuf_state =
intel_atomic_get_new_dbuf_state(state);
+ int tracker_state_service;
if (!HAS_MBUS_JOINING(i915))
return;
+ tracker_state_service =
+ get_mbus_mdclk_cdclk_ratio(i915,
+ dbuf_state->mdclk_cdclk_ratio,
+ dbuf_state->joined_mbus);
+
/*
* TODO: Implement vblank synchronized MBUS joining changes.
* Must be properly coordinated with dbuf reprogramming.
@@ -3494,13 +3510,15 @@ static void update_mbus_pre_enable(struct intel_atomic_state *state)
if (dbuf_state->joined_mbus) {
mbus_ctl = MBUS_HASHING_MODE_1x4 | MBUS_JOIN |
MBUS_JOIN_PIPE_SELECT_NONE;
- dbuf_min_tracker_val = DBUF_MIN_TRACKER_STATE_SERVICE(3);
} else {
mbus_ctl = MBUS_HASHING_MODE_2x2 |
MBUS_JOIN_PIPE_SELECT_NONE;
- dbuf_min_tracker_val = DBUF_MIN_TRACKER_STATE_SERVICE(1);
}
+ dbuf_min_tracker_val = DBUF_MIN_TRACKER_STATE_SERVICE(tracker_state_service);
+
+ mbus_ctl |= MBUS_TRANS_THROTTLE_MIN_SELECT(dbuf_state->mdclk_cdclk_ratio);
+
intel_de_rmw(i915, MBUS_CTL,
MBUS_HASHING_MODE_MASK | MBUS_JOIN |
MBUS_JOIN_PIPE_SELECT_MASK, mbus_ctl);
@@ -3521,7 +3539,8 @@ void intel_dbuf_pre_plane_update(struct intel_atomic_state *state)
if (!new_dbuf_state ||
(new_dbuf_state->enabled_slices == old_dbuf_state->enabled_slices &&
- new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus))
+ new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus &&
+ new_dbuf_state->mdclk_cdclk_ratio == old_dbuf_state->mdclk_cdclk_ratio))
return;
WARN_ON(!new_dbuf_state->base.changed);
@@ -3542,7 +3561,8 @@ void intel_dbuf_post_plane_update(struct intel_atomic_state *state)
if (!new_dbuf_state ||
(new_dbuf_state->enabled_slices == old_dbuf_state->enabled_slices &&
- new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus))
+ new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus &&
+ new_dbuf_state->mdclk_cdclk_ratio == old_dbuf_state->mdclk_cdclk_ratio))
return;
WARN_ON(!new_dbuf_state->base.changed);
@@ -56,6 +56,7 @@ struct intel_dbuf_state {
u8 slices[I915_MAX_PIPES];
u8 enabled_slices;
u8 active_pipes;
+ u8 mdclk_cdclk_ratio;
bool joined_mbus;
};
@@ -38,6 +38,8 @@
#define MBUS_HASHING_MODE_2x2 REG_FIELD_PREP(MBUS_HASHING_MODE_MASK, 0)
#define MBUS_HASHING_MODE_1x4 REG_FIELD_PREP(MBUS_HASHING_MODE_MASK, 1)
#define MBUS_JOIN_PIPE_SELECT_MASK REG_GENMASK(28, 26)
+#define MBUS_TRANS_THROTTLE_MIN_MASK REG_GENMASK(15, 13)
+#define MBUS_TRANS_THROTTLE_MIN_SELECT(ratio) REG_FIELD_PREP(MBUS_TRANS_THROTTLE_MIN_MASK, ratio)
#define MBUS_JOIN_PIPE_SELECT(pipe) REG_FIELD_PREP(MBUS_JOIN_PIPE_SELECT_MASK, pipe)
#define MBUS_JOIN_PIPE_SELECT_NONE MBUS_JOIN_PIPE_SELECT(7)