summaryrefslogtreecommitdiff
path: root/sys/dev/pci/drm/i915
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2024-08-13 00:28:10 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2024-08-13 00:28:10 +0000
commitd8e858a12aafd076d44bd625f52572f641222d8e (patch)
tree1ead20ca7c07af7db403d1a7a940b22b77e57f8c /sys/dev/pci/drm/i915
parent8b9677881f35adf9aaf2758d6296fa2d9e64c3f0 (diff)
drm/i915: Try to relocate the BIOS fb to the start of ggtt
From Ville Syrjala a8153627520a2d468680bb7686fd404c222b13ca in mainline linux
Diffstat (limited to 'sys/dev/pci/drm/i915')
-rw-r--r--sys/dev/pci/drm/i915/display/i9xx_plane.c30
-rw-r--r--sys/dev/pci/drm/i915/display/i9xx_plane.h2
-rw-r--r--sys/dev/pci/drm/i915/display/intel_display.c5
-rw-r--r--sys/dev/pci/drm/i915/display/intel_display_core.h2
-rw-r--r--sys/dev/pci/drm/i915/display/intel_plane_initial.c53
-rw-r--r--sys/dev/pci/drm/i915/display/skl_universal_plane.c28
-rw-r--r--sys/dev/pci/drm/i915/display/skl_universal_plane.h2
7 files changed, 120 insertions, 2 deletions
diff --git a/sys/dev/pci/drm/i915/display/i9xx_plane.c b/sys/dev/pci/drm/i915/display/i9xx_plane.c
index b1048832445..88ced3a89c5 100644
--- a/sys/dev/pci/drm/i915/display/i9xx_plane.c
+++ b/sys/dev/pci/drm/i915/display/i9xx_plane.c
@@ -1059,3 +1059,33 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
plane_config->fb = intel_fb;
}
+
+bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc,
+ const struct intel_initial_plane_config *plane_config)
+{
+ struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct intel_plane *plane = to_intel_plane(crtc->base.primary);
+ const struct intel_plane_state *plane_state =
+ to_intel_plane_state(plane->base.state);
+ enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
+ u32 base;
+
+ if (!plane_state->uapi.visible)
+ return false;
+
+ base = intel_plane_ggtt_offset(plane_state);
+
+ /*
+ * We may have moved the surface to a different
+ * part of ggtt, make the plane aware of that.
+ */
+ if (plane_config->base == base)
+ return false;
+
+ if (DISPLAY_VER(dev_priv) >= 4)
+ intel_de_write(dev_priv, DSPSURF(i9xx_plane), base);
+ else
+ intel_de_write(dev_priv, DSPADDR(i9xx_plane), base);
+
+ return true;
+}
diff --git a/sys/dev/pci/drm/i915/display/i9xx_plane.h b/sys/dev/pci/drm/i915/display/i9xx_plane.h
index 9d05438016a..200c5f9efb1 100644
--- a/sys/dev/pci/drm/i915/display/i9xx_plane.h
+++ b/sys/dev/pci/drm/i915/display/i9xx_plane.h
@@ -26,4 +26,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe);
void i9xx_get_initial_plane_config(struct intel_crtc *crtc,
struct intel_initial_plane_config *plane_config);
+bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc,
+ const struct intel_initial_plane_config *plane_config);
#endif
diff --git a/sys/dev/pci/drm/i915/display/intel_display.c b/sys/dev/pci/drm/i915/display/intel_display.c
index db597fb6f91..d8e194b240e 100644
--- a/sys/dev/pci/drm/i915/display/intel_display.c
+++ b/sys/dev/pci/drm/i915/display/intel_display.c
@@ -7764,6 +7764,7 @@ static const struct intel_display_funcs skl_display_funcs = {
.crtc_disable = hsw_crtc_disable,
.commit_modeset_enables = skl_commit_modeset_enables,
.get_initial_plane_config = skl_get_initial_plane_config,
+ .fixup_initial_plane_config = skl_fixup_initial_plane_config,
};
static const struct intel_display_funcs ddi_display_funcs = {
@@ -7772,6 +7773,7 @@ static const struct intel_display_funcs ddi_display_funcs = {
.crtc_disable = hsw_crtc_disable,
.commit_modeset_enables = intel_commit_modeset_enables,
.get_initial_plane_config = i9xx_get_initial_plane_config,
+ .fixup_initial_plane_config = i9xx_fixup_initial_plane_config,
};
static const struct intel_display_funcs pch_split_display_funcs = {
@@ -7780,6 +7782,7 @@ static const struct intel_display_funcs pch_split_display_funcs = {
.crtc_disable = ilk_crtc_disable,
.commit_modeset_enables = intel_commit_modeset_enables,
.get_initial_plane_config = i9xx_get_initial_plane_config,
+ .fixup_initial_plane_config = i9xx_fixup_initial_plane_config,
};
static const struct intel_display_funcs vlv_display_funcs = {
@@ -7788,6 +7791,7 @@ static const struct intel_display_funcs vlv_display_funcs = {
.crtc_disable = i9xx_crtc_disable,
.commit_modeset_enables = intel_commit_modeset_enables,
.get_initial_plane_config = i9xx_get_initial_plane_config,
+ .fixup_initial_plane_config = i9xx_fixup_initial_plane_config,
};
static const struct intel_display_funcs i9xx_display_funcs = {
@@ -7796,6 +7800,7 @@ static const struct intel_display_funcs i9xx_display_funcs = {
.crtc_disable = i9xx_crtc_disable,
.commit_modeset_enables = intel_commit_modeset_enables,
.get_initial_plane_config = i9xx_get_initial_plane_config,
+ .fixup_initial_plane_config = i9xx_fixup_initial_plane_config,
};
/**
diff --git a/sys/dev/pci/drm/i915/display/intel_display_core.h b/sys/dev/pci/drm/i915/display/intel_display_core.h
index 9e32d7d4af7..7bc606a468c 100644
--- a/sys/dev/pci/drm/i915/display/intel_display_core.h
+++ b/sys/dev/pci/drm/i915/display/intel_display_core.h
@@ -63,6 +63,8 @@ struct intel_display_funcs {
struct intel_crtc_state *);
void (*get_initial_plane_config)(struct intel_crtc *,
struct intel_initial_plane_config *);
+ bool (*fixup_initial_plane_config)(struct intel_crtc *crtc,
+ const struct intel_initial_plane_config *plane_config);
void (*crtc_enable)(struct intel_atomic_state *state,
struct intel_crtc *crtc);
void (*crtc_disable)(struct intel_atomic_state *state,
diff --git a/sys/dev/pci/drm/i915/display/intel_plane_initial.c b/sys/dev/pci/drm/i915/display/intel_plane_initial.c
index 48aaaeff940..4820a66de73 100644
--- a/sys/dev/pci/drm/i915/display/intel_plane_initial.c
+++ b/sys/dev/pci/drm/i915/display/intel_plane_initial.c
@@ -3,9 +3,11 @@
* Copyright © 2021 Intel Corporation
*/
+#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_region.h"
#include "i915_drv.h"
#include "intel_atomic_plane.h"
+#include "intel_crtc.h"
#include "intel_display.h"
#include "intel_display_types.h"
#include "intel_fb.h"
@@ -137,6 +139,7 @@ initial_plane_vma(struct drm_i915_private *i915,
{
struct intel_memory_region *mem;
struct drm_i915_gem_object *obj;
+ struct drm_mm_node orig_mm = {};
struct i915_vma *vma;
resource_size_t phys_base;
u32 base, size;
@@ -194,23 +197,66 @@ initial_plane_vma(struct drm_i915_private *i915,
goto err_obj;
}
+ /*
+ * MTL GOP likes to place the framebuffer high up in ggtt,
+ * which can cause problems for ggtt_reserve_guc_top().
+ * Try to pin it to a low ggtt address instead to avoid that.
+ */
+ base = 0;
+
+ if (base != plane_config->base) {
+ struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
+ int ret;
+
+ /*
+ * Make sure the original and new locations
+ * can't overlap. That would corrupt the original
+ * PTEs which are still being used for scanout.
+ */
+ ret = i915_gem_gtt_reserve(&ggtt->vm, NULL, &orig_mm,
+ size, plane_config->base,
+ I915_COLOR_UNEVICTABLE, PIN_NOEVICT);
+ if (ret)
+ goto err_obj;
+ }
+
vma = i915_vma_instance(obj, &to_gt(i915)->ggtt->vm, NULL);
if (IS_ERR(vma))
goto err_obj;
+retry:
pinctl = PIN_GLOBAL | PIN_OFFSET_FIXED | base;
- if (HAS_GMCH(i915))
+ if (!i915_gem_object_is_lmem(obj))
pinctl |= PIN_MAPPABLE;
- if (i915_vma_pin(vma, 0, 0, pinctl))
+ if (i915_vma_pin(vma, 0, 0, pinctl)) {
+ if (drm_mm_node_allocated(&orig_mm)) {
+ drm_mm_remove_node(&orig_mm);
+ /*
+ * Try again, but this time pin
+ * it to its original location.
+ */
+ base = plane_config->base;
+ goto retry;
+ }
goto err_obj;
+ }
if (i915_gem_object_is_tiled(obj) &&
!i915_vma_is_map_and_fenceable(vma))
goto err_obj;
+ if (drm_mm_node_allocated(&orig_mm))
+ drm_mm_remove_node(&orig_mm);
+
+ drm_dbg_kms(&i915->drm,
+ "Initial plane fb bound to 0x%x in the ggtt (original 0x%x)\n",
+ i915_ggtt_offset(vma), plane_config->base);
+
return vma;
err_obj:
+ if (drm_mm_node_allocated(&orig_mm))
+ drm_mm_remove_node(&orig_mm);
i915_gem_object_put(obj);
return NULL;
}
@@ -385,6 +431,9 @@ void intel_initial_plane_config(struct drm_i915_private *i915)
*/
intel_find_initial_plane_obj(crtc, plane_configs);
+ if (i915->display.funcs.display->fixup_initial_plane_config(crtc, plane_config))
+ intel_crtc_wait_for_next_vblank(crtc);
+
plane_config_fini(plane_config);
}
}
diff --git a/sys/dev/pci/drm/i915/display/skl_universal_plane.c b/sys/dev/pci/drm/i915/display/skl_universal_plane.c
index d557ecd4e1e..42906f1324d 100644
--- a/sys/dev/pci/drm/i915/display/skl_universal_plane.c
+++ b/sys/dev/pci/drm/i915/display/skl_universal_plane.c
@@ -2557,3 +2557,31 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
error:
kfree(intel_fb);
}
+
+bool skl_fixup_initial_plane_config(struct intel_crtc *crtc,
+ const struct intel_initial_plane_config *plane_config)
+{
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_plane *plane = to_intel_plane(crtc->base.primary);
+ const struct intel_plane_state *plane_state =
+ to_intel_plane_state(plane->base.state);
+ enum plane_id plane_id = plane->id;
+ enum pipe pipe = crtc->pipe;
+ u32 base;
+
+ if (!plane_state->uapi.visible)
+ return false;
+
+ base = intel_plane_ggtt_offset(plane_state);
+
+ /*
+ * We may have moved the surface to a different
+ * part of ggtt, make the plane aware of that.
+ */
+ if (plane_config->base == base)
+ return false;
+
+ intel_de_write(i915, PLANE_SURF(pipe, plane_id), base);
+
+ return true;
+}
diff --git a/sys/dev/pci/drm/i915/display/skl_universal_plane.h b/sys/dev/pci/drm/i915/display/skl_universal_plane.h
index be64c201f9b..e92e00c01b2 100644
--- a/sys/dev/pci/drm/i915/display/skl_universal_plane.h
+++ b/sys/dev/pci/drm/i915/display/skl_universal_plane.h
@@ -22,6 +22,8 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
void skl_get_initial_plane_config(struct intel_crtc *crtc,
struct intel_initial_plane_config *plane_config);
+bool skl_fixup_initial_plane_config(struct intel_crtc *crtc,
+ const struct intel_initial_plane_config *plane_config);
int skl_format_to_fourcc(int format, bool rgb_order, bool alpha);