drm/i915: Try to relocate the BIOS fb to the start of ggtt
authorjsg <jsg@openbsd.org>
Tue, 13 Aug 2024 00:28:09 +0000 (00:28 +0000)
committerjsg <jsg@openbsd.org>
Tue, 13 Aug 2024 00:28:09 +0000 (00:28 +0000)
From Ville Syrjala
a8153627520a2d468680bb7686fd404c222b13ca in mainline linux

sys/dev/pci/drm/i915/display/i9xx_plane.c
sys/dev/pci/drm/i915/display/i9xx_plane.h
sys/dev/pci/drm/i915/display/intel_display.c
sys/dev/pci/drm/i915/display/intel_display_core.h
sys/dev/pci/drm/i915/display/intel_plane_initial.c
sys/dev/pci/drm/i915/display/skl_universal_plane.c
sys/dev/pci/drm/i915/display/skl_universal_plane.h

index b104883..88ced3a 100644 (file)
@@ -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;
+}
index 9d05438..200c5f9 100644 (file)
@@ -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
index db597fb..d8e194b 100644 (file)
@@ -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,
 };
 
 /**
index 9e32d7d..7bc606a 100644 (file)
@@ -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,
index 48aaaef..4820a66 100644 (file)
@@ -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);
        }
 }
index d557ecd..42906f1 100644 (file)
@@ -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;
+}
index be64c20..e92e00c 100644 (file)
@@ -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);