From f4dc008632260d981c2afc6d72a0a31ca4c7191c Mon Sep 17 00:00:00 2001 From: Vandita Kulkarni Date: Tue, 18 May 2021 17:06:17 -0700 Subject: [PATCH] drm/i915/adl_p: MBUS programming MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Update MBUS_CTL register if the 2 mbus can be joined as per the current DDB allocation and active pipes, also update hashing mode and pipe select bits as per the sequence mentioned in the bspec. Cc: Stanislav Lisovskiy Cc: José Roberto de Souza Signed-off-by: Vandita Kulkarni Signed-off-by: Clinton Taylor Signed-off-by: Matt Roper Reviewed-by: Stanislav Lisovskiy Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20210519000625.3184321-10-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_atomic.c | 20 ++++++ drivers/gpu/drm/i915/display/intel_atomic.h | 1 + drivers/gpu/drm/i915/display/intel_display.c | 3 + drivers/gpu/drm/i915/i915_reg.h | 11 ++++ drivers/gpu/drm/i915/intel_pm.c | 92 +++++++++++++++++++++++++--- drivers/gpu/drm/i915/intel_pm.h | 2 +- 6 files changed, 120 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 45feaad..ca2aa7b 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -198,6 +198,26 @@ intel_connector_needs_modeset(struct intel_atomic_state *state, new_conn_state->crtc))); } +/** + * intel_any_crtc_needs_modeset - check if any CRTC needs a modeset + * @state: the atomic state corresponding to this modeset + * + * Returns true if any CRTC in @state needs a modeset. + */ +bool intel_any_crtc_needs_modeset(struct intel_atomic_state *state) +{ + struct intel_crtc *crtc; + struct intel_crtc_state *crtc_state; + int i; + + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { + if (intel_crtc_needs_modeset(crtc_state)) + return true; + } + + return false; +} + struct intel_digital_connector_state * intel_atomic_get_digital_connector_state(struct intel_atomic_state *state, struct intel_connector *connector) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.h b/drivers/gpu/drm/i915/display/intel_atomic.h index 62a3365..d2700c7 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.h +++ b/drivers/gpu/drm/i915/display/intel_atomic.h @@ -35,6 +35,7 @@ struct drm_connector_state * intel_digital_connector_duplicate_state(struct drm_connector *connector); bool intel_connector_needs_modeset(struct intel_atomic_state *state, struct drm_connector *connector); +bool intel_any_crtc_needs_modeset(struct intel_atomic_state *state); struct intel_digital_connector_state * intel_atomic_get_digital_connector_state(struct intel_atomic_state *state, struct intel_connector *connector); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index b9d908f..58be548e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -9957,6 +9957,9 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) goto fail; + if (intel_any_crtc_needs_modeset(state)) + any_ms = true; + if (any_ms) { ret = intel_modeset_checks(state); if (ret) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 192b3db..649b733 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2929,6 +2929,15 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define MBUS_BBOX_CTL_S1 _MMIO(0x45040) #define MBUS_BBOX_CTL_S2 _MMIO(0x45044) +#define MBUS_CTL _MMIO(0x4438C) +#define MBUS_JOIN REG_BIT(31) +#define MBUS_HASHING_MODE_MASK REG_BIT(30) +#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_JOIN_PIPE_SELECT(pipe) REG_FIELD_PREP(MBUS_JOIN_PIPE_SELECT_MASK, pipe) +#define MBUS_JOIN_PIPE_SELECT_NONE MBUS_JOIN_PIPE_SELECT(7) + #define HDPORT_STATE _MMIO(0x45050) #define HDPORT_DPLL_USED_MASK REG_GENMASK(15, 12) #define HDPORT_DDI_USED(phy) REG_BIT(2 * (phy) + 1) @@ -8149,6 +8158,8 @@ enum { #define DBUF_POWER_STATE REG_BIT(30) #define DBUF_TRACKER_STATE_SERVICE_MASK REG_GENMASK(23, 19) #define DBUF_TRACKER_STATE_SERVICE(x) REG_FIELD_PREP(DBUF_TRACKER_STATE_SERVICE_MASK, x) +#define DBUF_MIN_TRACKER_STATE_SERVICE_MASK REG_GENMASK(18, 16) /* ADL-P+ */ +#define DBUF_MIN_TRACKER_STATE_SERVICE(x) REG_FIELD_PREP(DBUF_MIN_TRACKER_STATE_SERVICE_MASK, x) /* ADL-P+ */ #define GEN7_MSG_CTL _MMIO(0x45010) #define WAIT_FOR_PCH_RESET_ACK (1 << 1) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cbbd966..00f3dea 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4266,7 +4266,6 @@ skl_cursor_allocation(const struct intel_crtc_state *crtc_state, static void skl_ddb_entry_init_from_hw(struct drm_i915_private *dev_priv, struct skl_ddb_entry *entry, u32 reg) { - entry->start = reg & DDB_ENTRY_MASK; entry->end = (reg >> DDB_ENTRY_END_SHIFT) & DDB_ENTRY_MASK; @@ -4391,6 +4390,7 @@ skl_plane_downscale_amount(const struct intel_crtc_state *crtc_state, struct dbuf_slice_conf_entry { u8 active_pipes; u8 dbuf_mask[I915_MAX_PIPES]; + bool join_mbus; }; /* @@ -4583,14 +4583,16 @@ static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = { { .active_pipes = BIT(PIPE_A), .dbuf_mask = { - [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2), + [PIPE_A] = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | BIT(DBUF_S4), }, + .join_mbus = true, }, { .active_pipes = BIT(PIPE_B), .dbuf_mask = { - [PIPE_B] = BIT(DBUF_S3) | BIT(DBUF_S4), + [PIPE_B] = BIT(DBUF_S1) | BIT(DBUF_S2) | BIT(DBUF_S3) | BIT(DBUF_S4), }, + .join_mbus = true, }, { .active_pipes = BIT(PIPE_A) | BIT(PIPE_B), @@ -4691,6 +4693,23 @@ static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = { }; +static bool check_mbus_joined(u8 active_pipes, + const struct dbuf_slice_conf_entry *dbuf_slices) +{ + int i; + + for (i = 0; i < dbuf_slices[i].active_pipes; i++) { + if (dbuf_slices[i].active_pipes == active_pipes) + return dbuf_slices[i].join_mbus; + } + return false; +} + +static bool adlp_check_mbus_joined(u8 active_pipes) +{ + return check_mbus_joined(active_pipes, adlp_allowed_dbufs); +} + static u8 compute_dbuf_slices(enum pipe pipe, u8 active_pipes, const struct dbuf_slice_conf_entry *dbuf_slices) { @@ -5972,16 +5991,29 @@ skl_compute_ddb(struct intel_atomic_state *state) new_dbuf_state->enabled_slices = intel_dbuf_enabled_slices(new_dbuf_state); - if (old_dbuf_state->enabled_slices != new_dbuf_state->enabled_slices) { + if (IS_ALDERLAKE_P(dev_priv)) + new_dbuf_state->joined_mbus = adlp_check_mbus_joined(new_dbuf_state->active_pipes); + + if (old_dbuf_state->enabled_slices != new_dbuf_state->enabled_slices || + old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) { ret = intel_atomic_serialize_global_state(&new_dbuf_state->base); if (ret) return ret; + if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) { + /* TODO: Implement vblank synchronized MBUS joining changes */ + ret = intel_modeset_all_pipes(state); + if (ret) + return ret; + } + drm_dbg_kms(&dev_priv->drm, - "Enabled dbuf slices 0x%x -> 0x%x (total dbuf slices 0x%x)\n", + "Enabled dbuf slices 0x%x -> 0x%x (total dbuf slices 0x%x), mbus joined? %s->%s\n", old_dbuf_state->enabled_slices, new_dbuf_state->enabled_slices, - INTEL_INFO(dev_priv)->dbuf.slice_mask); + INTEL_INFO(dev_priv)->dbuf.slice_mask, + yesno(old_dbuf_state->joined_mbus), + yesno(new_dbuf_state->joined_mbus)); } for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { @@ -6433,6 +6465,9 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv) to_intel_dbuf_state(dev_priv->dbuf.obj.state); struct intel_crtc *crtc; + if (IS_ALDERLAKE_P(dev_priv)) + dbuf_state->joined_mbus = intel_de_read(dev_priv, MBUS_CTL) & MBUS_JOIN; + for_each_intel_crtc(&dev_priv->drm, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); @@ -6472,10 +6507,11 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv) crtc_state->wm.skl.ddb.end = mbus_offset + dbuf_state->ddb[pipe].end; drm_dbg_kms(&dev_priv->drm, - "[CRTC:%d:%s] dbuf slices 0x%x, ddb (%d - %d), active pipes 0x%x\n", + "[CRTC:%d:%s] dbuf slices 0x%x, ddb (%d - %d), active pipes 0x%x, mbus joined: %s\n", crtc->base.base.id, crtc->base.name, dbuf_state->slices[pipe], dbuf_state->ddb[pipe].start, - dbuf_state->ddb[pipe].end, dbuf_state->active_pipes); + dbuf_state->ddb[pipe].end, dbuf_state->active_pipes, + yesno(dbuf_state->joined_mbus)); } dbuf_state->enabled_slices = dev_priv->dbuf.enabled_slices; @@ -8009,6 +8045,45 @@ int intel_dbuf_init(struct drm_i915_private *dev_priv) return 0; } +/* + * Configure MBUS_CTL and all DBUF_CTL_S of each slice to join_mbus state before + * update the request state of all DBUS slices. + */ +static void update_mbus_pre_enable(struct intel_atomic_state *state) +{ + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + u32 mbus_ctl, dbuf_min_tracker_val; + enum dbuf_slice slice; + const struct intel_dbuf_state *dbuf_state = + intel_atomic_get_new_dbuf_state(state); + + if (!IS_ALDERLAKE_P(dev_priv)) + return; + + /* + * TODO: Implement vblank synchronized MBUS joining changes. + * Must be properly coordinated with dbuf reprogramming. + */ + 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); + } + + intel_de_rmw(dev_priv, MBUS_CTL, + MBUS_HASHING_MODE_MASK | MBUS_JOIN | + MBUS_JOIN_PIPE_SELECT_MASK, mbus_ctl); + + for_each_dbuf_slice(dev_priv, slice) + intel_de_rmw(dev_priv, DBUF_CTL_S(slice), + DBUF_MIN_TRACKER_STATE_SERVICE_MASK, + dbuf_min_tracker_val); +} + void intel_dbuf_pre_plane_update(struct intel_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); @@ -8023,6 +8098,7 @@ void intel_dbuf_pre_plane_update(struct intel_atomic_state *state) WARN_ON(!new_dbuf_state->base.changed); + update_mbus_pre_enable(state); gen9_dbuf_slices_update(dev_priv, old_dbuf_state->enabled_slices | new_dbuf_state->enabled_slices); diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h index 669c8d5..bac72c8 100644 --- a/drivers/gpu/drm/i915/intel_pm.h +++ b/drivers/gpu/drm/i915/intel_pm.h @@ -78,9 +78,9 @@ struct intel_dbuf_state { struct skl_ddb_entry ddb[I915_MAX_PIPES]; unsigned int weight[I915_MAX_PIPES]; u8 slices[I915_MAX_PIPES]; - u8 enabled_slices; u8 active_pipes; + bool joined_mbus; }; int intel_dbuf_init(struct drm_i915_private *dev_priv); -- 2.7.4