To successfully hand off the display from BIOS to the Xe driver (fastboot),
we must accurately reconstruct the initial plane state and wrap the
firmware-allocated framebuffer.
This patch addresses several issues preventing this:
1. **Physical Address Resolution**: Instead of assuming a linear offset,
read the GGTT PTEs directly in `initial_plane_phys_smem` to resolve
the actual physical address of the BIOS framebuffer.
2. **Stolen Memory Management**: Register the TTM driver manager for
`XE_PL_STOLEN` in `xe_ttm_stolen_mgr_init`. This is required to
allocate/wrap buffer objects in stolen memory for the initial plane.
3. **Active State enforcement**: Force `uapi.active` to true for all CRTCs
during `intel_initial_plane_config`. The software state might not
yet reflect the hardware state (left active by BIOS), and this ensures
the driver attempts to read out the configuration.
4. **Visual Verification**: Write a test gradient pattern to the
initial framebuffer upon successful mapping to verify write access
and correct mapping.
Signed-off-by: Juasheem Sultan <[email protected]>
---
drivers/gpu/drm/i915/display/intel_plane_initial.c | 53 ++++++++++++++++++++++
drivers/gpu/drm/xe/display/xe_plane_initial.c | 28 +++++++++++-
drivers/gpu/drm/xe/xe_ggtt.h | 3 ++
drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c | 2 +
4 files changed, 85 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c
b/drivers/gpu/drm/i915/display/intel_plane_initial.c
index
a9f36b1b50c1da90bfd0a69538009e8c330d9b2b..2ffdb274bc36b4ee344ce6b61e226ce32d20f1e9
100644
--- a/drivers/gpu/drm/i915/display/intel_plane_initial.c
+++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c
@@ -121,6 +121,51 @@ initial_plane_phys(struct intel_display *display,
return true;
}
+static bool
+initial_plane_phys_smem(struct intel_display *display,
+ struct intel_initial_plane_config *plane_config)
+{
+ struct drm_i915_private *i915 = to_i915(display->drm);
+ gen8_pte_t __iomem *gte = to_gt(i915)->ggtt->gsm;
+ struct intel_memory_region *mem;
+ dma_addr_t dma_addr;
+ gen8_pte_t pte;
+ u32 base;
+
+ base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT);
+
+ gte += base / I915_GTT_PAGE_SIZE;
+
+ pte = ioread64(gte);
+
+ dma_addr = pte & GEN12_GGTT_PTE_ADDR_MASK;
+
+ mem = i915->mm.stolen_region;
+ if (!mem) {
+ drm_dbg_kms(display->drm,
+ "Initial plane memory region not initialized\n");
+ return false;
+ }
+
+ /* FIXME get and validate the dma_addr from the PTE */
+ plane_config->phys_base = dma_addr;
+ plane_config->mem = mem;
+
+ return true;
+}
+
+static bool
+initial_plane_phys(struct intel_display *display,
+ struct intel_initial_plane_config *plane_config)
+{
+ struct drm_i915_private *i915 = to_i915(display->drm);
+
+ if (IS_DGFX(i915) || HAS_LMEMBAR_SMEM_STOLEN(i915))
+ return initial_plane_phys_lmem(display, plane_config);
+ else
+ return initial_plane_phys_smem(display, plane_config);
+}
+
static struct i915_vma *
initial_plane_vma(struct intel_display *display,
struct intel_initial_plane_config *plane_config)
@@ -405,6 +450,14 @@ void intel_initial_plane_config(struct intel_display
*display)
struct intel_initial_plane_config plane_configs[I915_MAX_PIPES] = {};
struct intel_crtc *crtc;
+ /*
+ * BIOS is messy and may leave the CRTCs active, but the driver's
software
+ * state may not reflect that. We need to poke the driver to ensure
that
+ * it thinks the CRTCs are active, otherwise the plane scan won't
happen.
+ */
+ for_each_intel_crtc(display->drm, crtc)
+ to_intel_crtc_state(crtc->base.state)->uapi.active = true;
+
for_each_intel_crtc(display->drm, crtc) {
struct intel_initial_plane_config *plane_config =
&plane_configs[crtc->pipe];
diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c
b/drivers/gpu/drm/xe/display/xe_plane_initial.c
index
94f00def811bc138767540065c538b19c7816ed5..6a987224e90dc5620194a277ec5f52820da5efce
100644
--- a/drivers/gpu/drm/xe/display/xe_plane_initial.c
+++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c
@@ -192,6 +192,24 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
}
/* Reference handed over to fb */
xe_bo_put(bo);
+ if (bo->vmap.vaddr && plane_config->fb) {
+ int x, y;
+ void *vaddr = bo->vmap.vaddr;
+ u32 height = plane_config->fb->base.height;
+ u32 width = plane_config->fb->base.width;
+ u32 pitch = plane_config->fb->base.pitches[0];
+
+ for (y = 0; y < height; y++) {
+ u8 red = 255 * (height - y) / height;
+ u8 blue = 255 * y / height;
+ u32 color = (0xFF << 24) | (red << 16) | blue;
+ u32 *row = (u32 *)((u8 *)vaddr + y * pitch);
+
+ for (x = 0; x < width; x++) {
+ row[x] = color;
+ }
+ }
+ }
return true;
@@ -268,6 +286,8 @@ intel_find_initial_plane_obj(struct intel_crtc *crtc,
* simplest solution is to just disable the primary plane now and
* pretend the BIOS never had it enabled.
*/
+ to_intel_crtc_state(crtc->base.state)->hw.active = false;
+ to_intel_crtc_state(crtc->base.state)->uapi.active = false;
intel_plane_disable_noatomic(crtc, plane);
}
@@ -288,7 +308,13 @@ void intel_initial_plane_config(struct intel_display
*display)
{
struct intel_initial_plane_config plane_configs[I915_MAX_PIPES] = {};
struct intel_crtc *crtc;
-
+ /*
+ * BIOS is messy and may leave the CRTCs active, but the drive's
software
+ * state may not reflect that. We need to poke the driver to
ensure that
+ * it thinks the CRTCs are active, otherwise the plane scan wo't
happen.
+ */
+ for_each_intel_crtc(display->drm, crtc)
+ to_intel_crtc_state(crtc->base.state)->uapi.active = true;
for_each_intel_crtc(display->drm, crtc) {
struct intel_initial_plane_config *plane_config =
&plane_configs[crtc->pipe];
diff --git a/drivers/gpu/drm/xe/xe_ggtt.h b/drivers/gpu/drm/xe/xe_ggtt.h
index
75fc7a1efea7634d2dae0925cc6953fbc096041a..f34e2bc3b15c037dd862a6e68dd5481fbd3e8a9a
100644
--- a/drivers/gpu/drm/xe/xe_ggtt.h
+++ b/drivers/gpu/drm/xe/xe_ggtt.h
@@ -6,8 +6,11 @@
#ifndef _XE_GGTT_H_
#define _XE_GGTT_H_
+#include <linux/bits.h>
#include "xe_ggtt_types.h"
+#define GEN12_GGTT_PTE_ADDR_MASK GENMASK_ULL(45, 12)
+
struct drm_printer;
struct xe_tile;
struct drm_exec;
diff --git a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c
b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c
index
dc588255674d0e5e564d3cb260fe4e4fbe70c4eb..310ae85147d56d3fdfc46db2d2fd7e2553fbb1a7
100644
--- a/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c
+++ b/drivers/gpu/drm/xe/xe_ttm_stolen_mgr.c
@@ -256,6 +256,8 @@ int xe_ttm_stolen_mgr_init(struct xe_device *xe)
if (io_size)
mgr->mapping = devm_ioremap_wc(&pdev->dev, mgr->io_base,
io_size);
+ ttm_set_driver_manager(&xe->ttm, XE_PL_STOLEN, &mgr->base.manager);
+
return 0;
}
--
2.52.0.457.g6b5491de43-goog