+++ /dev/null
-From f37369add07a90e7fa0b7df826e27f7bae06c6ff Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 4 Feb 2022 16:18:18 +0200
-Subject: drm/i915: Workaround broken BIOS DBUF configuration on TGL/RKL
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Ville Syrjälä <ville.syrjala@linux.intel.com>
-
-[ Upstream commit 4e6f55120c7eccf6f9323bb681632e23cbcb3f3c ]
-
-On TGL/RKL the BIOS likes to use some kind of bogus DBUF layout
-that doesn't match what the spec recommends. With a single active
-pipe that is not going to be a problem, but with multiple pipes
-active skl_commit_modeset_enables() goes into an infinite loop
-since it can't figure out any order in which it can commit the
-pipes without causing DBUF overlaps between the planes.
-
-We'd need some kind of extra DBUF defrag stage in between to
-make the transition possible. But that is clearly way too complex
-a solution, so in the name of simplicity let's just sanitize the
-DBUF state by simply turning off all planes when we detect a
-pipe encroaching on its neighbours' DBUF slices. We only have
-to disable the primary planes as all other planes should have
-already been disabled (if they somehow were enabled) by
-earlier sanitization steps.
-
-And for good measure let's also sanitize in case the DBUF
-allocations of the pipes already seem to overlap each other.
-
-Cc: <stable@vger.kernel.org> # v5.14+
-Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4762
-Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
-Link: https://patchwork.freedesktop.org/patch/msgid/20220204141818.1900-3-ville.syrjala@linux.intel.com
-Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
-(cherry picked from commit 15512021eb3975a8c2366e3883337e252bb0eee5)
-Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/gpu/drm/i915/display/intel_display.c | 1 +
- drivers/gpu/drm/i915/intel_pm.c | 68 ++++++++++++++++++++
- drivers/gpu/drm/i915/intel_pm.h | 1 +
- 3 files changed, 70 insertions(+)
-
-diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
-index 625ce6975eeba..dd9cfb193432c 100644
---- a/drivers/gpu/drm/i915/display/intel_display.c
-+++ b/drivers/gpu/drm/i915/display/intel_display.c
-@@ -13217,6 +13217,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev,
- vlv_wm_sanitize(dev_priv);
- } else if (DISPLAY_VER(dev_priv) >= 9) {
- skl_wm_get_hw_state(dev_priv);
-+ skl_wm_sanitize(dev_priv);
- } else if (HAS_PCH_SPLIT(dev_priv)) {
- ilk_wm_get_hw_state(dev_priv);
- }
-diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
-index 9c5e4758947b6..c7c8a556e401a 100644
---- a/drivers/gpu/drm/i915/intel_pm.c
-+++ b/drivers/gpu/drm/i915/intel_pm.c
-@@ -6681,6 +6681,74 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
- dbuf_state->enabled_slices = dev_priv->dbuf.enabled_slices;
- }
-
-+static bool skl_dbuf_is_misconfigured(struct drm_i915_private *i915)
-+{
-+ const struct intel_dbuf_state *dbuf_state =
-+ to_intel_dbuf_state(i915->dbuf.obj.state);
-+ struct skl_ddb_entry entries[I915_MAX_PIPES] = {};
-+ struct intel_crtc *crtc;
-+
-+ for_each_intel_crtc(&i915->drm, crtc) {
-+ const struct intel_crtc_state *crtc_state =
-+ to_intel_crtc_state(crtc->base.state);
-+
-+ entries[crtc->pipe] = crtc_state->wm.skl.ddb;
-+ }
-+
-+ for_each_intel_crtc(&i915->drm, crtc) {
-+ const struct intel_crtc_state *crtc_state =
-+ to_intel_crtc_state(crtc->base.state);
-+ u8 slices;
-+
-+ slices = skl_compute_dbuf_slices(crtc, dbuf_state->active_pipes,
-+ dbuf_state->joined_mbus);
-+ if (dbuf_state->slices[crtc->pipe] & ~slices)
-+ return true;
-+
-+ if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.ddb, entries,
-+ I915_MAX_PIPES, crtc->pipe))
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+void skl_wm_sanitize(struct drm_i915_private *i915)
-+{
-+ struct intel_crtc *crtc;
-+
-+ /*
-+ * On TGL/RKL (at least) the BIOS likes to assign the planes
-+ * to the wrong DBUF slices. This will cause an infinite loop
-+ * in skl_commit_modeset_enables() as it can't find a way to
-+ * transition between the old bogus DBUF layout to the new
-+ * proper DBUF layout without DBUF allocation overlaps between
-+ * the planes (which cannot be allowed or else the hardware
-+ * may hang). If we detect a bogus DBUF layout just turn off
-+ * all the planes so that skl_commit_modeset_enables() can
-+ * simply ignore them.
-+ */
-+ if (!skl_dbuf_is_misconfigured(i915))
-+ return;
-+
-+ drm_dbg_kms(&i915->drm, "BIOS has misprogrammed the DBUF, disabling all planes\n");
-+
-+ for_each_intel_crtc(&i915->drm, crtc) {
-+ struct intel_plane *plane = to_intel_plane(crtc->base.primary);
-+ const struct intel_plane_state *plane_state =
-+ to_intel_plane_state(plane->base.state);
-+ struct intel_crtc_state *crtc_state =
-+ to_intel_crtc_state(crtc->base.state);
-+
-+ if (plane_state->uapi.visible)
-+ intel_plane_disable_noatomic(crtc, plane);
-+
-+ drm_WARN_ON(&i915->drm, crtc_state->active_planes != 0);
-+
-+ memset(&crtc_state->wm.skl.ddb, 0, sizeof(crtc_state->wm.skl.ddb));
-+ }
-+}
-+
- static void ilk_pipe_wm_get_hw_state(struct intel_crtc *crtc)
- {
- struct drm_device *dev = crtc->base.dev;
-diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h
-index 91f23b7f0af2e..79d89fe22d8c8 100644
---- a/drivers/gpu/drm/i915/intel_pm.h
-+++ b/drivers/gpu/drm/i915/intel_pm.h
-@@ -48,6 +48,7 @@ void skl_pipe_wm_get_hw_state(struct intel_crtc *crtc,
- struct skl_pipe_wm *out);
- void g4x_wm_sanitize(struct drm_i915_private *dev_priv);
- void vlv_wm_sanitize(struct drm_i915_private *dev_priv);
-+void skl_wm_sanitize(struct drm_i915_private *dev_priv);
- bool intel_can_enable_sagv(struct drm_i915_private *dev_priv,
- const struct intel_bw_state *bw_state);
- void intel_sagv_pre_plane_update(struct intel_atomic_state *state);
---
-2.34.1
-