From c748b09c71b6b6f7c963ef97fc6a1340b0626daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 7 Sep 2023 15:25:40 +0300 Subject: [PATCH 01/15] drm/i915: Split intel_update_crtc() into two parts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split intel_update_crtc() into two parts such that the first part performs all the non-vblank evasion preparatory stuff, and the second part just does the vblank evasion stuff. For now we just call these back to back so that there is no funcitonal change. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230907122541.32261-3-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy (cherry picked from commit c39c93578106f035218078c300db6361cf6a326c) (cherry picked from commit 324f3a119af9f1822d50232097939c32b3f85c18) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/intel_display.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 978b6c83ba20..c8b67a66d6b3 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6555,8 +6555,8 @@ static void intel_enable_crtc(struct intel_atomic_state *state, intel_crtc_enable_pipe_crc(crtc); } -static void intel_update_crtc(struct intel_atomic_state *state, - struct intel_crtc *crtc) +static void intel_pre_update_crtc(struct intel_atomic_state *state, + struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(state->base.dev); const struct intel_crtc_state *old_crtc_state = @@ -6598,6 +6598,15 @@ static void intel_update_crtc(struct intel_atomic_state *state, intel_color_commit_noarm(new_crtc_state); intel_crtc_planes_update_noarm(state, crtc); +} + +static void intel_update_crtc(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); /* Perform vblank evasion around commit operation */ intel_pipe_update_start(state, crtc); @@ -6626,7 +6635,7 @@ static void intel_update_crtc(struct intel_atomic_state *state, * valid pipe configuration from the BIOS we need to take care * of enabling them on the CRTC's first fastset. */ - if (intel_crtc_needs_fastset(new_crtc_state) && !modeset && + if (intel_crtc_needs_fastset(new_crtc_state) && old_crtc_state->inherited) intel_crtc_arm_fifo_underrun(crtc, new_crtc_state); } @@ -6722,6 +6731,7 @@ static void intel_commit_modeset_enables(struct intel_atomic_state *state) continue; intel_enable_crtc(state, crtc); + intel_pre_update_crtc(state, crtc); intel_update_crtc(state, crtc); } } @@ -6774,6 +6784,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) entries[pipe] = new_crtc_state->wm.skl.ddb; update_pipes &= ~BIT(pipe); + intel_pre_update_crtc(state, crtc); intel_update_crtc(state, crtc); /* @@ -6841,6 +6852,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) entries[pipe] = new_crtc_state->wm.skl.ddb; update_pipes &= ~BIT(pipe); + intel_pre_update_crtc(state, crtc); intel_update_crtc(state, crtc); } From 79de77bfbd93893342404fd9a685056935bcb677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 5 Mar 2024 10:47:28 +0200 Subject: [PATCH 02/15] drm/i915: Precompute disable_pipes bitmask in intel_commit_modeset_disables() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copy the pipe bitmask based approach from skl_commit_modeset_enables() into intel_commit_modeset_disables(). This avoids doing so many duplicated checks in all the loops, and also let's WARN at the end if we screwed up somewhere and forgot to disable some pipe. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240305084730.19182-2-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy (cherry picked from commit 5efb03ce90cc2fba3920de8fa0f04bed0476abeb) Signed-off-by: Rakshith M O Reviewed-by: Manasi Navare (cherry picked from commit acb031ed613d2d77e6f23a11e5627c79dabd02fa) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/intel_display.c | 27 ++++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c8b67a66d6b3..0407a9a87b62 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6663,9 +6663,10 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, static void intel_commit_modeset_disables(struct intel_atomic_state *state) { + struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_crtc_state *new_crtc_state, *old_crtc_state; struct intel_crtc *crtc; - u32 handled = 0; + u8 disable_pipes = 0; int i; for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, @@ -6673,21 +6674,24 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) if (!intel_crtc_needs_modeset(new_crtc_state)) continue; + /* + * Needs to be done even for pipes + * that weren't enabled previously. + */ intel_pre_plane_update(state, crtc); if (!old_crtc_state->hw.active) continue; intel_crtc_disable_planes(state, crtc); + + disable_pipes |= BIT(crtc->pipe); } /* Only disable port sync and MST slaves */ for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - if (!intel_crtc_needs_modeset(new_crtc_state)) - continue; - - if (!old_crtc_state->hw.active) + if ((disable_pipes & BIT(crtc->pipe)) == 0) continue; /* In case of Transcoder port Sync master slave CRTCs can be @@ -6702,22 +6706,23 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) intel_old_crtc_state_disables(state, old_crtc_state, new_crtc_state, crtc); - handled |= BIT(crtc->pipe); + + disable_pipes &= ~BIT(crtc->pipe); } /* Disable everything else left on */ for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - if (!intel_crtc_needs_modeset(new_crtc_state) || - (handled & BIT(crtc->pipe))) - continue; - - if (!old_crtc_state->hw.active) + if ((disable_pipes & BIT(crtc->pipe)) == 0) continue; intel_old_crtc_state_disables(state, old_crtc_state, new_crtc_state, crtc); + + disable_pipes &= ~BIT(crtc->pipe); } + + drm_WARN_ON(&i915->drm, disable_pipes); } static void intel_commit_modeset_enables(struct intel_atomic_state *state) From 63764e68209b6d3d42a0da439d9fa0eca48f2042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 7 Sep 2023 15:25:41 +0300 Subject: [PATCH 03/15] drm/i915: Do plane/etc. updates more atomically across pipes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Perform all the intel_pre_update_crtc() stuff for all pipes first, and only then do the intel_update_crtc() vblank evasion stuff for every pipe back to back. This should make it more likely that the plane updates from multiple pipes happen on the same frame (assuming the pipes are running in sync, eg. due to bigjoiner or port sync). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20230907122541.32261-4-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy (cherry picked from commit c610e841f19d57233062868f2408349e9ecade91) (cherry picked from commit 7b97392bda11e57c4ded41768971796956dd451a) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/intel_display.c | 26 ++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 0407a9a87b62..5d554e52330a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6737,6 +6737,12 @@ static void intel_commit_modeset_enables(struct intel_atomic_state *state) intel_enable_crtc(state, crtc); intel_pre_update_crtc(state, crtc); + } + + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + if (!new_crtc_state->hw.active) + continue; + intel_update_crtc(state, crtc); } } @@ -6774,6 +6780,15 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) * So first lets enable all pipes that do not need a fullmodeset as * those don't have any external dependency. */ + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + enum pipe pipe = crtc->pipe; + + if ((update_pipes & BIT(pipe)) == 0) + continue; + + intel_pre_update_crtc(state, crtc); + } + while (update_pipes) { for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { @@ -6789,7 +6804,6 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) entries[pipe] = new_crtc_state->wm.skl.ddb; update_pipes &= ~BIT(pipe); - intel_pre_update_crtc(state, crtc); intel_update_crtc(state, crtc); /* @@ -6845,6 +6859,15 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) /* * Finally we do the plane updates/etc. for all pipes that got enabled. */ + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + enum pipe pipe = crtc->pipe; + + if ((update_pipes & BIT(pipe)) == 0) + continue; + + intel_pre_update_crtc(state, crtc); + } + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { enum pipe pipe = crtc->pipe; @@ -6857,7 +6880,6 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) entries[pipe] = new_crtc_state->wm.skl.ddb; update_pipes &= ~BIT(pipe); - intel_pre_update_crtc(state, crtc); intel_update_crtc(state, crtc); } From 04a8335daa163b301ec5be6f132d70734e815a0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 5 Mar 2024 10:47:29 +0200 Subject: [PATCH 04/15] drm/i915: Disable planes more atomically during modesets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow in the footsteps of commit c610e841f19d ("drm/i915: Do plane/etc. updates more atomically across pipes") and do the plane disables back to back for all pipes also when we are disabling pipes. This should provide for a potentially more atomic user experience, which might be especially nice when using joiner or tiled displays. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240305084730.19182-3-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy (cherry picked from commit 4bc6745df2dbc315dc5a29a8b79020a74bd8fdd9) Signed-off-by: Rakshith M O Reviewed-by: Manasi Navare (cherry picked from commit cfd72221356477ddcb9207e082d5685ae03d233a) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/intel_display.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 5d554e52330a..b2052b052946 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6683,11 +6683,16 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) if (!old_crtc_state->hw.active) continue; - intel_crtc_disable_planes(state, crtc); - disable_pipes |= BIT(crtc->pipe); } + for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) { + if ((disable_pipes & BIT(crtc->pipe)) == 0) + continue; + + intel_crtc_disable_planes(state, crtc); + } + /* Only disable port sync and MST slaves */ for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { From 6e76209f8bc338a68774a3294fb9e76a9ccd2014 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Tue, 12 Mar 2024 13:36:36 -0300 Subject: [PATCH 05/15] drm/i915: Add mdclk_cdclk_ratio to intel_dbuf_state Xe2LPD always selects the CDCLK PLL as source for the MDCLK. Because of that, the ratio between MDCLK and CDCLK is not be constant anymore. As such, make sure to have the current ratio available in intel_dbuf_state so that it can be used during dbuf programming. Note that we write-lock the global state instead of serializing to a hardware commit because a change in the ratio should be rather handled in the CDCLK change sequence, which will need to take care of updating the necessary registers in that case. We will implement that in upcoming changes. That said, changes in the MBus joining state should be handled by the DBUF/MBUS logic, just like it is already done, but the logic will need to know the ratio to properly update the registers. v2: - Make first sentence of commit message more intelligible. (Matt) Reviewed-by: Matt Roper Signed-off-by: Gustavo Sousa Link: https://patchwork.freedesktop.org/patch/msgid/20240312163639.172321-6-gustavo.sousa@intel.com Signed-off-by: Lucas De Marchi (cherry picked from commit 9161e31181440e4882f78e02783e40325dc82e27) Conflicts: drivers/gpu/drm/i915/display/intel_cdclk.c (cherry picked from commit e446734708a5fa11132d024043df6db5c1549561) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/intel_cdclk.c | 25 ++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_cdclk.h | 2 ++ drivers/gpu/drm/i915/display/skl_watermark.c | 18 +++++++++++++- drivers/gpu/drm/i915/display/skl_watermark.h | 3 +++ 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 0c8e8fc31f4e..d0395ef4b98e 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -38,6 +38,7 @@ #include "intel_pcode.h" #include "intel_psr.h" #include "intel_vdsc.h" +#include "skl_watermark.h" #include "vlv_sideband.h" /** @@ -1779,6 +1780,21 @@ static int cdclk_squash_divider(u16 waveform) return hweight16(waveform ?: 0xffff); } +static bool mdclk_source_is_cdclk_pll(struct drm_i915_private *i915) +{ + return DISPLAY_VER(i915) >= 20; +} + +u8 intel_mdclk_cdclk_ratio(struct drm_i915_private *i915, + const struct intel_cdclk_config *cdclk_config) +{ + if (mdclk_source_is_cdclk_pll(i915)) + return DIV_ROUND_UP(cdclk_config->vco, cdclk_config->cdclk); + + /* Otherwise, source for MDCLK is CD2XCLK. */ + return 2; +} + static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i915, const struct intel_cdclk_config *old_cdclk_config, const struct intel_cdclk_config *new_cdclk_config, @@ -3148,6 +3164,15 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) "Modeset required for cdclk change\n"); } + if (intel_mdclk_cdclk_ratio(dev_priv, &old_cdclk_state->actual) != + intel_mdclk_cdclk_ratio(dev_priv, &new_cdclk_state->actual)) { + u8 ratio = intel_mdclk_cdclk_ratio(dev_priv, &new_cdclk_state->actual); + + ret = intel_dbuf_state_set_mdclk_cdclk_ratio(state, ratio); + if (ret) + return ret; + } + drm_dbg_kms(&dev_priv->drm, "New cdclk calculated to be logical %u kHz, actual %u kHz\n", new_cdclk_state->logical.cdclk, diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h index 71bc032bfef1..5c74aaf7d412 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.h +++ b/drivers/gpu/drm/i915/display/intel_cdclk.h @@ -65,6 +65,8 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv); u32 intel_read_rawclk(struct drm_i915_private *dev_priv); bool intel_cdclk_needs_modeset(const struct intel_cdclk_config *a, const struct intel_cdclk_config *b); +u8 intel_mdclk_cdclk_ratio(struct drm_i915_private *i915, + const struct intel_cdclk_config *cdclk_config); void intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state); void intel_set_cdclk_post_plane_update(struct intel_atomic_state *state); void intel_cdclk_dump_config(struct drm_i915_private *i915, diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index e48369983eb1..77155d5a2c73 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -2999,6 +2999,8 @@ static void skl_wm_get_hw_state(struct drm_i915_private *i915) if (HAS_MBUS_JOINING(i915)) dbuf_state->joined_mbus = intel_de_read(i915, MBUS_CTL) & MBUS_JOIN; + dbuf_state->mdclk_cdclk_ratio = intel_mdclk_cdclk_ratio(i915, &i915->display.cdclk.hw); + for_each_intel_crtc(&i915->drm, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); @@ -3472,6 +3474,19 @@ int intel_dbuf_init(struct drm_i915_private *i915) return 0; } +int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, u8 ratio) +{ + struct intel_dbuf_state *dbuf_state; + + dbuf_state = intel_atomic_get_dbuf_state(state); + if (IS_ERR(dbuf_state)) + return PTR_ERR(dbuf_state); + + dbuf_state->mdclk_cdclk_ratio = ratio; + + return intel_atomic_lock_global_state(&dbuf_state->base); +} + static void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, u8 ratio, bool joined_mbus) @@ -3516,7 +3531,8 @@ static void update_mbus_pre_enable(struct intel_atomic_state *state) MBUS_HASHING_MODE_MASK | MBUS_JOIN | MBUS_JOIN_PIPE_SELECT_MASK, mbus_ctl); - intel_dbuf_mdclk_cdclk_ratio_update(i915, 2, dbuf_state->joined_mbus); + intel_dbuf_mdclk_cdclk_ratio_update(i915, dbuf_state->mdclk_cdclk_ratio, + dbuf_state->joined_mbus); } void intel_dbuf_pre_plane_update(struct intel_atomic_state *state) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.h b/drivers/gpu/drm/i915/display/skl_watermark.h index fb0da36fd3ec..97ecc6da7515 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.h +++ b/drivers/gpu/drm/i915/display/skl_watermark.h @@ -58,6 +58,7 @@ struct intel_dbuf_state { u8 slices[I915_MAX_PIPES]; u8 enabled_slices; u8 active_pipes; + u8 mdclk_cdclk_ratio; bool joined_mbus; }; @@ -71,6 +72,8 @@ intel_atomic_get_dbuf_state(struct intel_atomic_state *state); to_intel_dbuf_state(intel_atomic_get_new_global_obj_state(state, &to_i915(state->base.dev)->display.dbuf.obj)) int intel_dbuf_init(struct drm_i915_private *i915); +int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, u8 ratio); + void intel_dbuf_pre_plane_update(struct intel_atomic_state *state); void intel_dbuf_post_plane_update(struct intel_atomic_state *state); void intel_mbus_dbox_update(struct intel_atomic_state *state); From 0b626486b9be95bc04c0ceeca8dbec5446f5d622 Mon Sep 17 00:00:00 2001 From: Gustavo Sousa Date: Tue, 12 Mar 2024 13:36:37 -0300 Subject: [PATCH 06/15] drm/i915/xe2lpd: Support MDCLK:CDCLK ratio changes Commit 394b4b7df9f7 ("drm/i915/lnl: Add CDCLK table") and commit 3d3696c0fed1 ("drm/i915/lnl: Start using CDCLK through PLL") started adding support for CDCLK programming support for Xe2LPD. One final piece is missing, which is the programming necessary for changed in the ratio between MDCLK and CDCLK. Let's do that now. BSpec instructs us to update MBUS_CTL and DBUF_CTL_S* registers when the ratio between MDCLK and CDCLK changes. The updates must be done before changing the CDCLK when decreasing the frequency; or after it when increasing the frequency. Ratio-related updates to MBUS_CTL also depend on the state of MBus joining, so they are performed by either CDCLK change sequence or by changes in MBus joining. Since one might happen independently of the other, we need to make sure that both logics see the necessary state values when programming that register. MBus joining logic needs to know the MDCLK:CDCLK ratio and that's already provided via mdclk_cdclk_ratio field of struct intel_dbuf_state. For the CDCLK logic, we need to have something similar: we need to propagate the status of MBus joining to struct intel_cdclk_state. Do that by adding the field joined_mbus to struct intel_cdclk_config. (Preferably, that field would be added to intel_cdclk_state, however currently only intel_cdclk_config is passed down to the functions that do the register programming. We might revisit this decision if we find that refactoring the code to pass the whole intel_cdclk_state is worth it.) Bspec: 68864, 68868, 69090, 69482 Reviewed-by: Stanislav Lisovskiy Signed-off-by: Gustavo Sousa Link: https://patchwork.freedesktop.org/patch/msgid/20240312163639.172321-7-gustavo.sousa@intel.com Signed-off-by: Lucas De Marchi (cherry picked from commit c834a080a0134e7bd0cb18c3a2b0dd674794d182) (cherry picked from commit 21a6eb124db1e9e4319adfb840d513d0af066381) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/intel_cdclk.c | 31 ++++++++++++++ drivers/gpu/drm/i915/display/intel_cdclk.h | 3 ++ drivers/gpu/drm/i915/display/skl_watermark.c | 40 +++++++++++++++---- drivers/gpu/drm/i915/display/skl_watermark.h | 1 + .../gpu/drm/i915/display/skl_watermark_regs.h | 18 +++++---- 5 files changed, 77 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index d0395ef4b98e..72b01e12aee6 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -39,6 +39,7 @@ #include "intel_psr.h" #include "intel_vdsc.h" #include "skl_watermark.h" +#include "skl_watermark_regs.h" #include "vlv_sideband.h" /** @@ -1581,6 +1582,8 @@ static void bxt_get_cdclk(struct drm_i915_private *dev_priv, } out: + if (DISPLAY_VER(dev_priv) >= 20) + cdclk_config->joined_mbus = intel_de_read(dev_priv, MBUS_CTL) & MBUS_JOIN; /* * Can't read this out :( Let's assume it's * at least what the CDCLK frequency requires. @@ -1795,6 +1798,14 @@ u8 intel_mdclk_cdclk_ratio(struct drm_i915_private *i915, return 2; } +static void xe2lpd_mdclk_cdclk_ratio_program(struct drm_i915_private *i915, + const struct intel_cdclk_config *cdclk_config) +{ + intel_dbuf_mdclk_cdclk_ratio_update(i915, + intel_mdclk_cdclk_ratio(i915, cdclk_config), + cdclk_config->joined_mbus); +} + static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i915, const struct intel_cdclk_config *old_cdclk_config, const struct intel_cdclk_config *new_cdclk_config, @@ -1948,6 +1959,9 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, return; } + if (DISPLAY_VER(dev_priv) >= 20 && cdclk < dev_priv->display.cdclk.hw.cdclk) + xe2lpd_mdclk_cdclk_ratio_program(dev_priv, cdclk_config); + if (cdclk_compute_crawl_and_squash_midpoint(dev_priv, &dev_priv->display.cdclk.hw, cdclk_config, &mid_cdclk_config)) { _bxt_set_cdclk(dev_priv, &mid_cdclk_config, pipe); @@ -1956,6 +1970,9 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, _bxt_set_cdclk(dev_priv, cdclk_config, pipe); } + if (DISPLAY_VER(dev_priv) >= 20 && cdclk > dev_priv->display.cdclk.hw.cdclk) + xe2lpd_mdclk_cdclk_ratio_program(dev_priv, cdclk_config); + if (DISPLAY_VER(dev_priv) >= 14) /* * NOOP - No Pcode communication needed for @@ -3043,6 +3060,20 @@ int intel_cdclk_atomic_check(struct intel_atomic_state *state, return 0; } +int intel_cdclk_state_set_joined_mbus(struct intel_atomic_state *state, bool joined_mbus) +{ + struct intel_cdclk_state *cdclk_state; + + cdclk_state = intel_atomic_get_cdclk_state(state); + if (IS_ERR(cdclk_state)) + return PTR_ERR(cdclk_state); + + cdclk_state->actual.joined_mbus = joined_mbus; + cdclk_state->logical.joined_mbus = joined_mbus; + + return intel_atomic_lock_global_state(&cdclk_state->base); +} + int intel_cdclk_init(struct drm_i915_private *dev_priv) { struct intel_cdclk_state *cdclk_state; diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h index 5c74aaf7d412..376f8305a402 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.h +++ b/drivers/gpu/drm/i915/display/intel_cdclk.h @@ -18,6 +18,8 @@ struct intel_crtc_state; struct intel_cdclk_config { unsigned int cdclk, vco, ref, bypass; u8 voltage_level; + /* This field is only valid for Xe2LPD and above. */ + bool joined_mbus; }; struct intel_cdclk_state { @@ -77,6 +79,7 @@ void intel_cdclk_get_cdclk(struct drm_i915_private *dev_priv, struct intel_cdclk_config *cdclk_config); int intel_cdclk_atomic_check(struct intel_atomic_state *state, bool *need_cdclk_calc); +int intel_cdclk_state_set_joined_mbus(struct intel_atomic_state *state, bool joined_mbus); struct intel_cdclk_state * intel_atomic_get_cdclk_state(struct intel_atomic_state *state); diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 77155d5a2c73..19fcb2dfe24a 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -12,6 +12,7 @@ #include "intel_atomic.h" #include "intel_atomic_plane.h" #include "intel_bw.h" +#include "intel_cdclk.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_display.h" @@ -2587,10 +2588,17 @@ skl_compute_ddb(struct intel_atomic_state *state) return ret; } - if (HAS_MBUS_JOINING(i915)) + if (HAS_MBUS_JOINING(i915)) { new_dbuf_state->joined_mbus = adlp_check_mbus_joined(new_dbuf_state->active_pipes); + if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) { + ret = intel_cdclk_state_set_joined_mbus(state, new_dbuf_state->joined_mbus); + if (ret) + return ret; + } + } + for_each_intel_crtc(&i915->drm, crtc) { enum pipe pipe = crtc->pipe; @@ -3487,12 +3495,14 @@ int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, u8 return intel_atomic_lock_global_state(&dbuf_state->base); } -static void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, - u8 ratio, - bool joined_mbus) +void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, u8 ratio, bool joined_mbus) { enum dbuf_slice slice; + if (DISPLAY_VER(i915) >= 20) + intel_de_rmw(i915, MBUS_CTL, MBUS_TRANSLATION_THROTTLE_MIN_MASK, + MBUS_TRANSLATION_THROTTLE_MIN(ratio - 1)); + if (joined_mbus) ratio *= 2; @@ -3510,7 +3520,9 @@ static void update_mbus_pre_enable(struct intel_atomic_state *state) { struct drm_i915_private *i915 = to_i915(state->base.dev); u32 mbus_ctl; - const struct intel_dbuf_state *dbuf_state = + const struct intel_dbuf_state *old_dbuf_state = + intel_atomic_get_old_dbuf_state(state); + const struct intel_dbuf_state *new_dbuf_state = intel_atomic_get_new_dbuf_state(state); if (!HAS_MBUS_JOINING(i915)) @@ -3520,7 +3532,7 @@ static void update_mbus_pre_enable(struct intel_atomic_state *state) * TODO: Implement vblank synchronized MBUS joining changes. * Must be properly coordinated with dbuf reprogramming. */ - if (dbuf_state->joined_mbus) + if (new_dbuf_state->joined_mbus) mbus_ctl = MBUS_HASHING_MODE_1x4 | MBUS_JOIN | MBUS_JOIN_PIPE_SELECT_NONE; else @@ -3531,8 +3543,20 @@ static void update_mbus_pre_enable(struct intel_atomic_state *state) MBUS_HASHING_MODE_MASK | MBUS_JOIN | MBUS_JOIN_PIPE_SELECT_MASK, mbus_ctl); - intel_dbuf_mdclk_cdclk_ratio_update(i915, dbuf_state->mdclk_cdclk_ratio, - dbuf_state->joined_mbus); + if (DISPLAY_VER(i915) >= 20 && + old_dbuf_state->mdclk_cdclk_ratio != new_dbuf_state->mdclk_cdclk_ratio) { + /* + * For Xe2LPD and beyond, when there is a change in the ratio + * between MDCLK and CDCLK, updates to related registers need to + * happen at a specific point in the CDCLK change sequence. In + * that case, we defer to the call to + * intel_dbuf_mdclk_cdclk_ratio_update() to the CDCLK logic. + */ + return; + } + + intel_dbuf_mdclk_cdclk_ratio_update(i915, new_dbuf_state->mdclk_cdclk_ratio, + new_dbuf_state->joined_mbus); } void intel_dbuf_pre_plane_update(struct intel_atomic_state *state) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.h b/drivers/gpu/drm/i915/display/skl_watermark.h index 97ecc6da7515..3eea87534d68 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.h +++ b/drivers/gpu/drm/i915/display/skl_watermark.h @@ -76,6 +76,7 @@ int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, u8 void intel_dbuf_pre_plane_update(struct intel_atomic_state *state); void intel_dbuf_post_plane_update(struct intel_atomic_state *state); +void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, u8 ratio, bool joined_mbus); void intel_mbus_dbox_update(struct intel_atomic_state *state); #endif /* __SKL_WATERMARK_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_watermark_regs.h b/drivers/gpu/drm/i915/display/skl_watermark_regs.h index 20b30c9a6613..269163fa3350 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark_regs.h +++ b/drivers/gpu/drm/i915/display/skl_watermark_regs.h @@ -32,14 +32,16 @@ #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 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 MBUS_TRANSLATION_THROTTLE_MIN_MASK REG_GENMASK(15, 13) +#define MBUS_TRANSLATION_THROTTLE_MIN(val) REG_FIELD_PREP(MBUS_TRANSLATION_THROTTLE_MIN_MASK, val) /* Watermark register definitions for SKL */ #define _CUR_WM_A_0 0x70140 From 1c9f75a7940dbd9aa4d17a455b3c037c5c95cbfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 2 Apr 2024 18:50:08 +0300 Subject: [PATCH 07/15] drm/i915: Relocate intel_mbus_dbox_update() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_mbus_dbox_update() will become static soon. Relocate it into a place that avoids having to add a forward declaration for it. Reviewed-by: Uma Shankar Reviewed-by: Gustavo Sousa Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240402155016.13733-7-ville.syrjala@linux.intel.com (cherry picked from commit 359e4f4fed29e446157d98cc7cbdc4ebaae81dd7) (cherry picked from commit ad1b6ecd14a34bddbe351d9a47b5a28ad02dd4af) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/skl_watermark.c | 166 +++++++++---------- 1 file changed, 83 insertions(+), 83 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 19fcb2dfe24a..57ebc5e9f08f 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3482,6 +3482,89 @@ int intel_dbuf_init(struct drm_i915_private *i915) return 0; } +static bool xelpdp_is_only_pipe_per_dbuf_bank(enum pipe pipe, u8 active_pipes) +{ + switch (pipe) { + case PIPE_A: + return !(active_pipes & BIT(PIPE_D)); + case PIPE_D: + return !(active_pipes & BIT(PIPE_A)); + case PIPE_B: + return !(active_pipes & BIT(PIPE_C)); + case PIPE_C: + return !(active_pipes & BIT(PIPE_B)); + default: /* to suppress compiler warning */ + MISSING_CASE(pipe); + break; + } + + return false; +} + +void intel_mbus_dbox_update(struct intel_atomic_state *state) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_dbuf_state *new_dbuf_state, *old_dbuf_state; + const struct intel_crtc *crtc; + u32 val = 0; + + if (DISPLAY_VER(i915) < 11) + return; + + new_dbuf_state = intel_atomic_get_new_dbuf_state(state); + old_dbuf_state = intel_atomic_get_old_dbuf_state(state); + if (!new_dbuf_state || + (new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus && + new_dbuf_state->active_pipes == old_dbuf_state->active_pipes)) + return; + + if (DISPLAY_VER(i915) >= 14) + val |= MBUS_DBOX_I_CREDIT(2); + + if (DISPLAY_VER(i915) >= 12) { + val |= MBUS_DBOX_B2B_TRANSACTIONS_MAX(16); + val |= MBUS_DBOX_B2B_TRANSACTIONS_DELAY(1); + val |= MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN; + } + + if (DISPLAY_VER(i915) >= 14) + val |= new_dbuf_state->joined_mbus ? MBUS_DBOX_A_CREDIT(12) : + MBUS_DBOX_A_CREDIT(8); + else if (IS_ALDERLAKE_P(i915)) + /* Wa_22010947358:adl-p */ + val |= new_dbuf_state->joined_mbus ? MBUS_DBOX_A_CREDIT(6) : + MBUS_DBOX_A_CREDIT(4); + else + val |= MBUS_DBOX_A_CREDIT(2); + + if (DISPLAY_VER(i915) >= 14) { + val |= MBUS_DBOX_B_CREDIT(0xA); + } else if (IS_ALDERLAKE_P(i915)) { + val |= MBUS_DBOX_BW_CREDIT(2); + val |= MBUS_DBOX_B_CREDIT(8); + } else if (DISPLAY_VER(i915) >= 12) { + val |= MBUS_DBOX_BW_CREDIT(2); + val |= MBUS_DBOX_B_CREDIT(12); + } else { + val |= MBUS_DBOX_BW_CREDIT(1); + val |= MBUS_DBOX_B_CREDIT(8); + } + + for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, new_dbuf_state->active_pipes) { + u32 pipe_val = val; + + if (DISPLAY_VER(i915) >= 14) { + if (xelpdp_is_only_pipe_per_dbuf_bank(crtc->pipe, + new_dbuf_state->active_pipes)) + pipe_val |= MBUS_DBOX_BW_8CREDITS_MTL; + else + pipe_val |= MBUS_DBOX_BW_4CREDITS_MTL; + } + + intel_de_write(i915, PIPE_MBUS_DBOX_CTL(crtc->pipe), pipe_val); + } +} + int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, u8 ratio) { struct intel_dbuf_state *dbuf_state; @@ -3599,89 +3682,6 @@ void intel_dbuf_post_plane_update(struct intel_atomic_state *state) new_dbuf_state->enabled_slices); } -static bool xelpdp_is_only_pipe_per_dbuf_bank(enum pipe pipe, u8 active_pipes) -{ - switch (pipe) { - case PIPE_A: - return !(active_pipes & BIT(PIPE_D)); - case PIPE_D: - return !(active_pipes & BIT(PIPE_A)); - case PIPE_B: - return !(active_pipes & BIT(PIPE_C)); - case PIPE_C: - return !(active_pipes & BIT(PIPE_B)); - default: /* to suppress compiler warning */ - MISSING_CASE(pipe); - break; - } - - return false; -} - -void intel_mbus_dbox_update(struct intel_atomic_state *state) -{ - struct drm_i915_private *i915 = to_i915(state->base.dev); - const struct intel_dbuf_state *new_dbuf_state, *old_dbuf_state; - const struct intel_crtc *crtc; - u32 val = 0; - - if (DISPLAY_VER(i915) < 11) - return; - - new_dbuf_state = intel_atomic_get_new_dbuf_state(state); - old_dbuf_state = intel_atomic_get_old_dbuf_state(state); - if (!new_dbuf_state || - (new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus && - new_dbuf_state->active_pipes == old_dbuf_state->active_pipes)) - return; - - if (DISPLAY_VER(i915) >= 14) - val |= MBUS_DBOX_I_CREDIT(2); - - if (DISPLAY_VER(i915) >= 12) { - val |= MBUS_DBOX_B2B_TRANSACTIONS_MAX(16); - val |= MBUS_DBOX_B2B_TRANSACTIONS_DELAY(1); - val |= MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN; - } - - if (DISPLAY_VER(i915) >= 14) - val |= new_dbuf_state->joined_mbus ? MBUS_DBOX_A_CREDIT(12) : - MBUS_DBOX_A_CREDIT(8); - else if (IS_ALDERLAKE_P(i915)) - /* Wa_22010947358:adl-p */ - val |= new_dbuf_state->joined_mbus ? MBUS_DBOX_A_CREDIT(6) : - MBUS_DBOX_A_CREDIT(4); - else - val |= MBUS_DBOX_A_CREDIT(2); - - if (DISPLAY_VER(i915) >= 14) { - val |= MBUS_DBOX_B_CREDIT(0xA); - } else if (IS_ALDERLAKE_P(i915)) { - val |= MBUS_DBOX_BW_CREDIT(2); - val |= MBUS_DBOX_B_CREDIT(8); - } else if (DISPLAY_VER(i915) >= 12) { - val |= MBUS_DBOX_BW_CREDIT(2); - val |= MBUS_DBOX_B_CREDIT(12); - } else { - val |= MBUS_DBOX_BW_CREDIT(1); - val |= MBUS_DBOX_B_CREDIT(8); - } - - for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, new_dbuf_state->active_pipes) { - u32 pipe_val = val; - - if (DISPLAY_VER(i915) >= 14) { - if (xelpdp_is_only_pipe_per_dbuf_bank(crtc->pipe, - new_dbuf_state->active_pipes)) - pipe_val |= MBUS_DBOX_BW_8CREDITS_MTL; - else - pipe_val |= MBUS_DBOX_BW_4CREDITS_MTL; - } - - intel_de_write(i915, PIPE_MBUS_DBOX_CTL(crtc->pipe), pipe_val); - } -} - static int skl_watermark_ipc_status_show(struct seq_file *m, void *data) { struct drm_i915_private *i915 = m->private; From 8be69b673232f4619cd9989ceca3e61c066fd59c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 2 Apr 2024 18:50:09 +0300 Subject: [PATCH 08/15] drm/i915: Extract intel_dbuf_mbus_join_update() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extact the stuff that writes the joining bits in MBUS_CTL into its own function. Will help with correctly sequencing the operations done during mbus programming. Reviewed-by: Uma Shankar Reviewed-by: Gustavo Sousa Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240402155016.13733-8-ville.syrjala@linux.intel.com (cherry picked from commit 8d7fc2612e4a161a63ed6cddcfe8d3205717b54d) (cherry picked from commit 36babad2404d11a89d0c1f383d5143e456de5cd8) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/skl_watermark.c | 35 ++++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 57ebc5e9f08f..944e79118374 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3595,21 +3595,12 @@ void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, u8 ratio DBUF_MIN_TRACKER_STATE_SERVICE(ratio - 1)); } -/* - * 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) +static void intel_dbuf_mbus_join_update(struct intel_atomic_state *state) { struct drm_i915_private *i915 = to_i915(state->base.dev); - u32 mbus_ctl; - const struct intel_dbuf_state *old_dbuf_state = - intel_atomic_get_old_dbuf_state(state); const struct intel_dbuf_state *new_dbuf_state = intel_atomic_get_new_dbuf_state(state); - - if (!HAS_MBUS_JOINING(i915)) - return; + u32 mbus_ctl; /* * TODO: Implement vblank synchronized MBUS joining changes. @@ -3625,6 +3616,28 @@ static void update_mbus_pre_enable(struct intel_atomic_state *state) intel_de_rmw(i915, MBUS_CTL, MBUS_HASHING_MODE_MASK | MBUS_JOIN | MBUS_JOIN_PIPE_SELECT_MASK, mbus_ctl); +} + +/* + * 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 *i915 = to_i915(state->base.dev); + const struct intel_dbuf_state *old_dbuf_state = + intel_atomic_get_old_dbuf_state(state); + const struct intel_dbuf_state *new_dbuf_state = + intel_atomic_get_new_dbuf_state(state); + + if (!HAS_MBUS_JOINING(i915)) + return; + + /* + * TODO: Implement vblank synchronized MBUS joining changes. + * Must be properly coordinated with dbuf reprogramming. + */ + intel_dbuf_mbus_join_update(state); if (DISPLAY_VER(i915) >= 20 && old_dbuf_state->mdclk_cdclk_ratio != new_dbuf_state->mdclk_cdclk_ratio) { From 94f98eacae94c28b20029292eb87e4293ed8e861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 2 Apr 2024 18:50:10 +0300 Subject: [PATCH 09/15] drm/i915: Extract intel_dbuf_mdclk_min_tracker_update() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the stuff that writes the dbuf/mbus ratio stuff into its own function. Will help with correctly sequencing the operations done during mbus programming. Reviewed-by: Uma Shankar Reviewed-by: Gustavo Sousa Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240402155016.13733-9-ville.syrjala@linux.intel.com (cherry picked from commit a2e83f27cc06b4f366e8d70ebc1d2659bd16ab62) (cherry picked from commit 3c5b231591bd5295fe3e8dbd7b460f6e265bb18e) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/skl_watermark.c | 43 ++++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 944e79118374..f658d053d890 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3595,6 +3595,30 @@ void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, u8 ratio DBUF_MIN_TRACKER_STATE_SERVICE(ratio - 1)); } +static void intel_dbuf_mdclk_min_tracker_update(struct intel_atomic_state *state) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_dbuf_state *old_dbuf_state = + intel_atomic_get_old_dbuf_state(state); + const struct intel_dbuf_state *new_dbuf_state = + intel_atomic_get_new_dbuf_state(state); + + if (DISPLAY_VER(i915) >= 20 && + old_dbuf_state->mdclk_cdclk_ratio != new_dbuf_state->mdclk_cdclk_ratio) { + /* + * For Xe2LPD and beyond, when there is a change in the ratio + * between MDCLK and CDCLK, updates to related registers need to + * happen at a specific point in the CDCLK change sequence. In + * that case, we defer to the call to + * intel_dbuf_mdclk_cdclk_ratio_update() to the CDCLK logic. + */ + return; + } + + intel_dbuf_mdclk_cdclk_ratio_update(i915, new_dbuf_state->mdclk_cdclk_ratio, + new_dbuf_state->joined_mbus); +} + static void intel_dbuf_mbus_join_update(struct intel_atomic_state *state) { struct drm_i915_private *i915 = to_i915(state->base.dev); @@ -3625,10 +3649,6 @@ static void intel_dbuf_mbus_join_update(struct intel_atomic_state *state) static void update_mbus_pre_enable(struct intel_atomic_state *state) { struct drm_i915_private *i915 = to_i915(state->base.dev); - const struct intel_dbuf_state *old_dbuf_state = - intel_atomic_get_old_dbuf_state(state); - const struct intel_dbuf_state *new_dbuf_state = - intel_atomic_get_new_dbuf_state(state); if (!HAS_MBUS_JOINING(i915)) return; @@ -3639,20 +3659,7 @@ static void update_mbus_pre_enable(struct intel_atomic_state *state) */ intel_dbuf_mbus_join_update(state); - if (DISPLAY_VER(i915) >= 20 && - old_dbuf_state->mdclk_cdclk_ratio != new_dbuf_state->mdclk_cdclk_ratio) { - /* - * For Xe2LPD and beyond, when there is a change in the ratio - * between MDCLK and CDCLK, updates to related registers need to - * happen at a specific point in the CDCLK change sequence. In - * that case, we defer to the call to - * intel_dbuf_mdclk_cdclk_ratio_update() to the CDCLK logic. - */ - return; - } - - intel_dbuf_mdclk_cdclk_ratio_update(i915, new_dbuf_state->mdclk_cdclk_ratio, - new_dbuf_state->joined_mbus); + intel_dbuf_mdclk_min_tracker_update(state); } void intel_dbuf_pre_plane_update(struct intel_atomic_state *state) From aa955823848a90864815f52eba4ce0198a62cb0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 2 Apr 2024 18:50:11 +0300 Subject: [PATCH 10/15] drm/i915: Add debugs for mbus joining and dbuf ratio programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some debugs so that we can actually observe what is actually happening during the mbus/dbuf programming steps. We can just shove them into fairly low level functions as none of them are called during any critical sections/etc. Reviewed-by: Uma Shankar Reviewed-by: Gustavo Sousa Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240402155016.13733-10-ville.syrjala@linux.intel.com (cherry picked from commit d91254e932b2a4e443f6086a8e511bba35108fce) (cherry picked from commit 91a5706a0e577b354890a99e1d89e4dd0ca76285) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/skl_watermark.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index f658d053d890..f3f6df16c8ae 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3589,6 +3589,9 @@ void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, u8 ratio if (joined_mbus) ratio *= 2; + drm_dbg_kms(&i915->drm, "Updating dbuf ratio to %d (mbus joined: %s)\n", + ratio, str_yes_no(joined_mbus)); + for_each_dbuf_slice(i915, slice) intel_de_rmw(i915, DBUF_CTL_S(slice), DBUF_MIN_TRACKER_STATE_SERVICE_MASK, @@ -3622,10 +3625,16 @@ static void intel_dbuf_mdclk_min_tracker_update(struct intel_atomic_state *state static void intel_dbuf_mbus_join_update(struct intel_atomic_state *state) { struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_dbuf_state *old_dbuf_state = + intel_atomic_get_old_dbuf_state(state); const struct intel_dbuf_state *new_dbuf_state = intel_atomic_get_new_dbuf_state(state); u32 mbus_ctl; + drm_dbg_kms(&i915->drm, "Changing mbus joined: %s -> %s\n", + str_yes_no(old_dbuf_state->joined_mbus), + str_yes_no(new_dbuf_state->joined_mbus)); + /* * TODO: Implement vblank synchronized MBUS joining changes. * Must be properly coordinated with dbuf reprogramming. From 878c981c412128106923e9fee3523cfece2f9351 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Tue, 2 Apr 2024 18:50:12 +0300 Subject: [PATCH 11/15] drm/i915: Use old mbus_join value when increasing CDCLK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to make sure we are not breaking the proper sequence let's do updates step by step and don't change MBUS join value during MDCLK/CDCLK programming stage. MBUS join programming would be taken care by pre/post ddb hooks. v2: - Reworded comment about using old mbus_join value in intel_set_cdclk(Ville Syrjälä) Reviewed-by: Uma Shankar Signed-off-by: Stanislav Lisovskiy [v3: vsyrjala: rebase on top of cdclk changes, reword a bit more] Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240402155016.13733-11-ville.syrjala@linux.intel.com (cherry picked from commit 48b85304c00c3b523a44d4cd96a8160becf3e3a4) (cherry picked from commit 7634402374da312cc9b9dd9408d8a4529bcb3794) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/intel_cdclk.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 72b01e12aee6..747b769c7009 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2512,6 +2512,12 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state) old_cdclk_state->actual.voltage_level); } + /* + * mbus joining will be changed later by + * intel_dbuf_mbus_{pre,post}_ddb_update() + */ + cdclk_config.joined_mbus = old_cdclk_state->actual.joined_mbus; + drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); intel_set_cdclk(i915, &cdclk_config, pipe); From 8f21c5a0d06ab923ee094e2303d11bb202ad06a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 2 Apr 2024 18:50:13 +0300 Subject: [PATCH 12/15] drm/i915: Use the correct mdclk/cdclk ratio in MBUS updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current cdclk/mbus programming sequence is as follows: 1. intel_set_cdclk_pre_plane_update() 2. update_mbus_pre_enable() 3. intel_set_cdclk_post_plane_update() when the actual mdclk/cdclk programming is postponed to intel_set_cdclk_post_plane_update() we must keep using the old mdclk/cdclk ratio during update_mbus_pre_enable(). This guarantees the programmed ratio matches the rest of the hardware state (mdlk/cdclk/mbus joining). v2: Extracted from the vblank synchronized mbus programming patch Cc: Gustavo Sousa Reviewed-by: Uma Shankar #v1 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240402155016.13733-12-ville.syrjala@linux.intel.com (cherry picked from commit bea9898561f1d38915128c57fd280a91e5048579) (cherry picked from commit df13785f21d5d9c69492c772c4a0518f4a4d31d2) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/intel_cdclk.c | 11 +++++++++++ drivers/gpu/drm/i915/display/intel_cdclk.h | 1 + drivers/gpu/drm/i915/display/skl_watermark.c | 19 ++++++++----------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 747b769c7009..abc137cd7713 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2471,6 +2471,17 @@ static void intel_cdclk_pcode_post_notify(struct intel_atomic_state *state) update_cdclk, update_pipe_count); } +bool intel_cdclk_is_decreasing_later(struct intel_atomic_state *state) +{ + const struct intel_cdclk_state *old_cdclk_state = + intel_atomic_get_old_cdclk_state(state); + const struct intel_cdclk_state *new_cdclk_state = + intel_atomic_get_new_cdclk_state(state); + + return new_cdclk_state && !new_cdclk_state->disable_pipes && + new_cdclk_state->actual.cdclk < old_cdclk_state->actual.cdclk; +} + /** * intel_set_cdclk_pre_plane_update - Push the CDCLK state to the hardware * @state: intel atomic state diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h index 376f8305a402..399fd639391e 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.h +++ b/drivers/gpu/drm/i915/display/intel_cdclk.h @@ -69,6 +69,7 @@ bool intel_cdclk_needs_modeset(const struct intel_cdclk_config *a, const struct intel_cdclk_config *b); u8 intel_mdclk_cdclk_ratio(struct drm_i915_private *i915, const struct intel_cdclk_config *cdclk_config); +bool intel_cdclk_is_decreasing_later(struct intel_atomic_state *state); void intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state); void intel_set_cdclk_post_plane_update(struct intel_atomic_state *state); void intel_cdclk_dump_config(struct drm_i915_private *i915, diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index f3f6df16c8ae..7eda1c4c21b5 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3605,20 +3605,17 @@ static void intel_dbuf_mdclk_min_tracker_update(struct intel_atomic_state *state intel_atomic_get_old_dbuf_state(state); const struct intel_dbuf_state *new_dbuf_state = intel_atomic_get_new_dbuf_state(state); + int mdclk_cdclk_ratio; - if (DISPLAY_VER(i915) >= 20 && - old_dbuf_state->mdclk_cdclk_ratio != new_dbuf_state->mdclk_cdclk_ratio) { - /* - * For Xe2LPD and beyond, when there is a change in the ratio - * between MDCLK and CDCLK, updates to related registers need to - * happen at a specific point in the CDCLK change sequence. In - * that case, we defer to the call to - * intel_dbuf_mdclk_cdclk_ratio_update() to the CDCLK logic. - */ - return; + if (intel_cdclk_is_decreasing_later(state)) { + /* cdclk/mdclk will be changed later by intel_set_cdclk_post_plane_update() */ + mdclk_cdclk_ratio = old_dbuf_state->mdclk_cdclk_ratio; + } else { + /* cdclk/mdclk already changed by intel_set_cdclk_pre_plane_update() */ + mdclk_cdclk_ratio = new_dbuf_state->mdclk_cdclk_ratio; } - intel_dbuf_mdclk_cdclk_ratio_update(i915, new_dbuf_state->mdclk_cdclk_ratio, + intel_dbuf_mdclk_cdclk_ratio_update(i915, mdclk_cdclk_ratio, new_dbuf_state->joined_mbus); } From cf5c3f19209ec7fd6bdbde5176c0525d3f1d03c7 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Tue, 2 Apr 2024 18:50:14 +0300 Subject: [PATCH 13/15] drm/i915: Implement vblank synchronized MBUS join changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we can't change MBUS join status without doing a modeset, because we are lacking mechanism to synchronize those with vblank. However then this means that we can't do a fastset, if there is a need to change MBUS join state. Fix that by implementing such change. We already call correspondent check and update at pre_plane dbuf update, so the only thing left is to have a non-modeset version of that. If active pipes stay the same then fastset is possible and only MBUS join state/ddb allocation updates would be committed. The full mbus/cdclk sequence will look as follows: 1. disable pipes 2. increase cdclk if necessary 2.1 reprogram cdclk 2.2 update dbuf tracker value 3. enable mbus joining if necessary 3.1 update mbus_ctl 3.2 update dbuf tracker value 4. reallocate dbuf for planes on active pipes 5. disable mbus joining if necessary 5.1 update dbuf tracker value 5.2 update mbus_ctl 6. enable pipes 7. decrease cdclk if necessary 7.1 update dbuf tracker value 7.2 reprogram cdclk And in order to keep things in sync we need: Step 2: - mbus_join == old - mdclk/cdclk ratio == new Step 3: - mbus_join == new - mdclk/cdclk ratio == old when cdclk is changing in step 7 - mdclk/cdclk ratio == new when cdclk is changing in step 2 Step 5: - mbus_join == new - mdclk/cdclk ratio == old when cdclk is changing in step 7 - mdclk/cdclk ratio == new when cdclk is changing in step 2 Step 7: - mbus_join == new - mdclk/cdclk ratio == new v2: - Removed redundant parentheses(Ville Syrjälä) - Constified new_crtc_state in intel_mbus_joined_pipe(Ville Syrjälä) - Removed pipe_select variable(Ville Syrjälä) [v3: vsyrjala: Correctly sequence vs. cdclk updates, properly describe the full sequence, shuffle code around to make the diff more legible, streamline a few things] [v4: vsyrjala: Move the intel_cdclk_is_decreasing_later() stuff to a separate patch] Cc: Gustavo Sousa Reviewed-by: Uma Shankar #v3 Signed-off-by: Stanislav Lisovskiy Co-developed-by: Ville Syrjälä Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240402155016.13733-13-ville.syrjala@linux.intel.com (cherry picked from commit 8c5dbb5039fd7ed4eb0062eaed793f86ee536dd7) (cherry picked from commit fea3cb41110ea4b4cf12a09d44c0a22a912d9a51) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/intel_display.c | 5 +- drivers/gpu/drm/i915/display/skl_watermark.c | 122 +++++++++++++------ drivers/gpu/drm/i915/display/skl_watermark.h | 3 +- 3 files changed, 92 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index b2052b052946..5d346a9eac58 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6794,6 +6794,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) intel_pre_update_crtc(state, crtc); } + intel_dbuf_mbus_pre_ddb_update(state); + while (update_pipes) { for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { @@ -6824,6 +6826,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) } } + intel_dbuf_mbus_post_ddb_update(state); + update_pipes = modeset_pipes; /* @@ -7094,7 +7098,6 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_encoders_update_prepare(state); intel_dbuf_pre_plane_update(state); - intel_mbus_dbox_update(state); for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { if (new_crtc_state->do_async_flip) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 7eda1c4c21b5..eea3f003aacf 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -2622,13 +2622,6 @@ skl_compute_ddb(struct intel_atomic_state *state) 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_late(state, "MBUS joining change"); - if (ret) - return ret; - } - drm_dbg_kms(&i915->drm, "Enabled dbuf slices 0x%x -> 0x%x (total dbuf slices 0x%x), mbus joined? %s->%s\n", old_dbuf_state->enabled_slices, @@ -3501,7 +3494,7 @@ static bool xelpdp_is_only_pipe_per_dbuf_bank(enum pipe pipe, u8 active_pipes) return false; } -void intel_mbus_dbox_update(struct intel_atomic_state *state) +static void intel_mbus_dbox_update(struct intel_atomic_state *state) { struct drm_i915_private *i915 = to_i915(state->base.dev); const struct intel_dbuf_state *new_dbuf_state, *old_dbuf_state; @@ -3582,6 +3575,9 @@ void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, u8 ratio { enum dbuf_slice slice; + if (!HAS_MBUS_JOINING(i915)) + return; + if (DISPLAY_VER(i915) >= 20) intel_de_rmw(i915, MBUS_CTL, MBUS_TRANSLATION_THROTTLE_MIN_MASK, MBUS_TRANSLATION_THROTTLE_MIN(ratio - 1)); @@ -3619,7 +3615,28 @@ static void intel_dbuf_mdclk_min_tracker_update(struct intel_atomic_state *state new_dbuf_state->joined_mbus); } -static void intel_dbuf_mbus_join_update(struct intel_atomic_state *state) +static enum pipe intel_mbus_joined_pipe(struct intel_atomic_state *state, + const struct intel_dbuf_state *dbuf_state) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + enum pipe pipe = ffs(dbuf_state->active_pipes) - 1; + const struct intel_crtc_state *new_crtc_state; + struct intel_crtc *crtc; + + drm_WARN_ON(&i915->drm, !dbuf_state->joined_mbus); + drm_WARN_ON(&i915->drm, !is_power_of_2(dbuf_state->active_pipes)); + + crtc = intel_crtc_for_pipe(i915, pipe); + new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + + if (new_crtc_state && !intel_crtc_needs_modeset(new_crtc_state)) + return pipe; + else + return INVALID_PIPE; +} + +static void intel_dbuf_mbus_join_update(struct intel_atomic_state *state, + enum pipe pipe) { struct drm_i915_private *i915 = to_i915(state->base.dev); const struct intel_dbuf_state *old_dbuf_state = @@ -3628,44 +3645,80 @@ static void intel_dbuf_mbus_join_update(struct intel_atomic_state *state) intel_atomic_get_new_dbuf_state(state); u32 mbus_ctl; - drm_dbg_kms(&i915->drm, "Changing mbus joined: %s -> %s\n", + drm_dbg_kms(&i915->drm, "Changing mbus joined: %s -> %s (pipe: %c)\n", str_yes_no(old_dbuf_state->joined_mbus), - str_yes_no(new_dbuf_state->joined_mbus)); + str_yes_no(new_dbuf_state->joined_mbus), + pipe != INVALID_PIPE ? pipe_name(pipe) : '*'); - /* - * TODO: Implement vblank synchronized MBUS joining changes. - * Must be properly coordinated with dbuf reprogramming. - */ if (new_dbuf_state->joined_mbus) - mbus_ctl = MBUS_HASHING_MODE_1x4 | MBUS_JOIN | - MBUS_JOIN_PIPE_SELECT_NONE; + mbus_ctl = MBUS_HASHING_MODE_1x4 | MBUS_JOIN; else - mbus_ctl = MBUS_HASHING_MODE_2x2 | - MBUS_JOIN_PIPE_SELECT_NONE; + mbus_ctl = MBUS_HASHING_MODE_2x2; + + if (pipe != INVALID_PIPE) + mbus_ctl |= MBUS_JOIN_PIPE_SELECT(pipe); + else + mbus_ctl |= MBUS_JOIN_PIPE_SELECT_NONE; intel_de_rmw(i915, MBUS_CTL, MBUS_HASHING_MODE_MASK | MBUS_JOIN | MBUS_JOIN_PIPE_SELECT_MASK, mbus_ctl); } -/* - * 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) +void intel_dbuf_mbus_pre_ddb_update(struct intel_atomic_state *state) +{ + const struct intel_dbuf_state *new_dbuf_state = + intel_atomic_get_new_dbuf_state(state); + const struct intel_dbuf_state *old_dbuf_state = + intel_atomic_get_old_dbuf_state(state); + + if (!new_dbuf_state) + return; + + if (!old_dbuf_state->joined_mbus && new_dbuf_state->joined_mbus) { + enum pipe pipe = intel_mbus_joined_pipe(state, new_dbuf_state); + + WARN_ON(!new_dbuf_state->base.changed); + + intel_dbuf_mbus_join_update(state, pipe); + intel_mbus_dbox_update(state); + intel_dbuf_mdclk_min_tracker_update(state); + } +} + +void intel_dbuf_mbus_post_ddb_update(struct intel_atomic_state *state) { struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_dbuf_state *new_dbuf_state = + intel_atomic_get_new_dbuf_state(state); + const struct intel_dbuf_state *old_dbuf_state = + intel_atomic_get_old_dbuf_state(state); - if (!HAS_MBUS_JOINING(i915)) + if (!new_dbuf_state) return; - /* - * TODO: Implement vblank synchronized MBUS joining changes. - * Must be properly coordinated with dbuf reprogramming. - */ - intel_dbuf_mbus_join_update(state); + if (old_dbuf_state->joined_mbus && !new_dbuf_state->joined_mbus) { + enum pipe pipe = intel_mbus_joined_pipe(state, old_dbuf_state); + + WARN_ON(!new_dbuf_state->base.changed); + + intel_dbuf_mdclk_min_tracker_update(state); + intel_mbus_dbox_update(state); + intel_dbuf_mbus_join_update(state, pipe); + + if (pipe != INVALID_PIPE) { + struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe); + + intel_crtc_wait_for_next_vblank(crtc); + } + } else if (old_dbuf_state->joined_mbus == new_dbuf_state->joined_mbus && + old_dbuf_state->active_pipes != new_dbuf_state->active_pipes) { + WARN_ON(!new_dbuf_state->base.changed); + + intel_dbuf_mdclk_min_tracker_update(state); + intel_mbus_dbox_update(state); + } - intel_dbuf_mdclk_min_tracker_update(state); } void intel_dbuf_pre_plane_update(struct intel_atomic_state *state) @@ -3677,13 +3730,11 @@ void intel_dbuf_pre_plane_update(struct intel_atomic_state *state) intel_atomic_get_old_dbuf_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->enabled_slices == old_dbuf_state->enabled_slices) return; WARN_ON(!new_dbuf_state->base.changed); - update_mbus_pre_enable(state); gen9_dbuf_slices_update(i915, old_dbuf_state->enabled_slices | new_dbuf_state->enabled_slices); @@ -3698,8 +3749,7 @@ void intel_dbuf_post_plane_update(struct intel_atomic_state *state) intel_atomic_get_old_dbuf_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->enabled_slices == old_dbuf_state->enabled_slices) return; WARN_ON(!new_dbuf_state->base.changed); diff --git a/drivers/gpu/drm/i915/display/skl_watermark.h b/drivers/gpu/drm/i915/display/skl_watermark.h index 3eea87534d68..73c68e0eebda 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.h +++ b/drivers/gpu/drm/i915/display/skl_watermark.h @@ -77,7 +77,8 @@ int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, u8 void intel_dbuf_pre_plane_update(struct intel_atomic_state *state); void intel_dbuf_post_plane_update(struct intel_atomic_state *state); void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, u8 ratio, bool joined_mbus); -void intel_mbus_dbox_update(struct intel_atomic_state *state); +void intel_dbuf_mbus_pre_ddb_update(struct intel_atomic_state *state); +void intel_dbuf_mbus_post_ddb_update(struct intel_atomic_state *state); #endif /* __SKL_WATERMARK_H__ */ From 2cdc4425a3dd087a63c386e850069b3fb2149da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 2 Apr 2024 18:50:15 +0300 Subject: [PATCH 14/15] drm/i915: Use a plain old int for the cdclk/mdclk ratio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No point in throwing around u8 when we're dealing with just an integer. Use a plain old boring 'int'. Reviewed-by: Uma Shankar Reviewed-by: Gustavo Sousa Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240402155016.13733-14-ville.syrjala@linux.intel.com (cherry picked from commit 96c420d5016e5bec57dccb161744c43366b72eca) Conflicts: drivers/gpu/drm/i915/display/intel_cdclk.c (cherry picked from commit 9bfa2b4ff064a27a02a836422918fec6123b6f6e) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/intel_cdclk.c | 6 +++--- drivers/gpu/drm/i915/display/intel_cdclk.h | 4 ++-- drivers/gpu/drm/i915/display/skl_watermark.c | 6 ++++-- drivers/gpu/drm/i915/display/skl_watermark.h | 6 ++++-- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index abc137cd7713..28764ce3edee 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -1788,8 +1788,8 @@ static bool mdclk_source_is_cdclk_pll(struct drm_i915_private *i915) return DISPLAY_VER(i915) >= 20; } -u8 intel_mdclk_cdclk_ratio(struct drm_i915_private *i915, - const struct intel_cdclk_config *cdclk_config) +int intel_mdclk_cdclk_ratio(struct drm_i915_private *i915, + const struct intel_cdclk_config *cdclk_config) { if (mdclk_source_is_cdclk_pll(i915)) return DIV_ROUND_UP(cdclk_config->vco, cdclk_config->cdclk); @@ -3214,7 +3214,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) if (intel_mdclk_cdclk_ratio(dev_priv, &old_cdclk_state->actual) != intel_mdclk_cdclk_ratio(dev_priv, &new_cdclk_state->actual)) { - u8 ratio = intel_mdclk_cdclk_ratio(dev_priv, &new_cdclk_state->actual); + int ratio = intel_mdclk_cdclk_ratio(dev_priv, &new_cdclk_state->actual); ret = intel_dbuf_state_set_mdclk_cdclk_ratio(state, ratio); if (ret) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h index 399fd639391e..6c97b61c569c 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.h +++ b/drivers/gpu/drm/i915/display/intel_cdclk.h @@ -67,8 +67,8 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv); u32 intel_read_rawclk(struct drm_i915_private *dev_priv); bool intel_cdclk_needs_modeset(const struct intel_cdclk_config *a, const struct intel_cdclk_config *b); -u8 intel_mdclk_cdclk_ratio(struct drm_i915_private *i915, - const struct intel_cdclk_config *cdclk_config); +int intel_mdclk_cdclk_ratio(struct drm_i915_private *i915, + const struct intel_cdclk_config *cdclk_config); bool intel_cdclk_is_decreasing_later(struct intel_atomic_state *state); void intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state); void intel_set_cdclk_post_plane_update(struct intel_atomic_state *state); diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index eea3f003aacf..24b22fccd6d8 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3558,7 +3558,8 @@ static void intel_mbus_dbox_update(struct intel_atomic_state *state) } } -int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, u8 ratio) +int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, + int ratio) { struct intel_dbuf_state *dbuf_state; @@ -3571,7 +3572,8 @@ int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, u8 return intel_atomic_lock_global_state(&dbuf_state->base); } -void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, u8 ratio, bool joined_mbus) +void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, + int ratio, bool joined_mbus) { enum dbuf_slice slice; diff --git a/drivers/gpu/drm/i915/display/skl_watermark.h b/drivers/gpu/drm/i915/display/skl_watermark.h index 73c68e0eebda..032eeffe65c4 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.h +++ b/drivers/gpu/drm/i915/display/skl_watermark.h @@ -72,11 +72,13 @@ intel_atomic_get_dbuf_state(struct intel_atomic_state *state); to_intel_dbuf_state(intel_atomic_get_new_global_obj_state(state, &to_i915(state->base.dev)->display.dbuf.obj)) int intel_dbuf_init(struct drm_i915_private *i915); -int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, u8 ratio); +int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, + int ratio); void intel_dbuf_pre_plane_update(struct intel_atomic_state *state); void intel_dbuf_post_plane_update(struct intel_atomic_state *state); -void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, u8 ratio, bool joined_mbus); +void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, + int ratio, bool joined_mbus); void intel_dbuf_mbus_pre_ddb_update(struct intel_atomic_state *state); void intel_dbuf_mbus_post_ddb_update(struct intel_atomic_state *state); From c6b4f07164044f151a58dd86c4566bb8a953b644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 2 Apr 2024 18:50:16 +0300 Subject: [PATCH 15/15] drm/i915: Optimize out redundant dbuf slice updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit if the new dbuf slices are a superset of the old dbuf slices then we don't have to do anything in intel_dbuf_post_plane_update(). Restructure the code to skip such redundant dbuf slice updates. The main benefit is slightly less confusing logs. Reviewed-by: Uma Shankar Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240402155016.13733-15-ville.syrjala@linux.intel.com (cherry picked from commit c8361cd3c449055683f4c3f40b129a14fa564918) (cherry picked from commit ce9c02ed9666bea7c76afcae73e3de2a14e2e021) Signed-off-by: Wentao Guan --- drivers/gpu/drm/i915/display/skl_watermark.c | 27 +++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index 24b22fccd6d8..480fddc0bdfd 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -3730,16 +3730,20 @@ void intel_dbuf_pre_plane_update(struct intel_atomic_state *state) intel_atomic_get_new_dbuf_state(state); const struct intel_dbuf_state *old_dbuf_state = intel_atomic_get_old_dbuf_state(state); + u8 old_slices, new_slices; - if (!new_dbuf_state || - new_dbuf_state->enabled_slices == old_dbuf_state->enabled_slices) + if (!new_dbuf_state) + return; + + old_slices = old_dbuf_state->enabled_slices; + new_slices = old_dbuf_state->enabled_slices | new_dbuf_state->enabled_slices; + + if (old_slices == new_slices) return; WARN_ON(!new_dbuf_state->base.changed); - gen9_dbuf_slices_update(i915, - old_dbuf_state->enabled_slices | - new_dbuf_state->enabled_slices); + gen9_dbuf_slices_update(i915, new_slices); } void intel_dbuf_post_plane_update(struct intel_atomic_state *state) @@ -3749,15 +3753,20 @@ void intel_dbuf_post_plane_update(struct intel_atomic_state *state) intel_atomic_get_new_dbuf_state(state); const struct intel_dbuf_state *old_dbuf_state = intel_atomic_get_old_dbuf_state(state); + u8 old_slices, new_slices; - if (!new_dbuf_state || - new_dbuf_state->enabled_slices == old_dbuf_state->enabled_slices) + if (!new_dbuf_state) + return; + + old_slices = old_dbuf_state->enabled_slices | new_dbuf_state->enabled_slices; + new_slices = new_dbuf_state->enabled_slices; + + if (old_slices == new_slices) return; WARN_ON(!new_dbuf_state->base.changed); - gen9_dbuf_slices_update(i915, - new_dbuf_state->enabled_slices); + gen9_dbuf_slices_update(i915, new_slices); } static int skl_watermark_ipc_status_show(struct seq_file *m, void *data)