drm/i915/display: Add drm_panic support for Y-tiling with DPT

On Alder Lake and later, it's not possible to disable tiling when DPT
is enabled.
So this commit implements Y-Tiling support, to still be able to draw
the panic screen.

Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
Link: https://lore.kernel.org/r/20250624091501.257661-10-jfalempe@redhat.com
Signed-off-by: Maarten Lankhorst <dev@lankhorst.se>
This commit is contained in:
Jocelyn Falempe
2025-06-24 11:01:18 +02:00
committed by Maarten Lankhorst
parent 31d886b674
commit 116d86dd69
5 changed files with 94 additions and 8 deletions

View File

@@ -1272,6 +1272,32 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
intel_plane_unpin_fb(old_plane_state);
}
/* Handle Y-tiling, only if DPT is enabled (otherwise disabling tiling is easier)
* All DPT hardware have 128-bytes width tiling, so Y-tile dimension is 32x32
* pixels for 32bits pixels.
*/
#define YTILE_WIDTH 32
#define YTILE_HEIGHT 32
#define YTILE_SIZE (YTILE_WIDTH * YTILE_HEIGHT * 4)
static unsigned int intel_ytile_get_offset(unsigned int width, unsigned int x, unsigned int y)
{
u32 offset;
unsigned int swizzle;
unsigned int width_in_blocks = DIV_ROUND_UP(width, 32);
/* Block offset */
offset = ((y / YTILE_HEIGHT) * width_in_blocks + (x / YTILE_WIDTH)) * YTILE_SIZE;
x = x % YTILE_WIDTH;
y = y % YTILE_HEIGHT;
/* bit order inside a block is x4 x3 x2 y4 y3 y2 y1 y0 x1 x0 */
swizzle = (x & 3) | ((y & 0x1f) << 2) | ((x & 0x1c) << 5);
offset += swizzle * 4;
return offset;
}
static void intel_panic_flush(struct drm_plane *plane)
{
struct intel_plane_state *plane_state = to_intel_plane_state(plane->state);
@@ -1295,6 +1321,35 @@ static void intel_panic_flush(struct drm_plane *plane)
iplane->disable_tiling(iplane);
}
static unsigned int (*intel_get_tiling_func(u64 fb_modifier))(unsigned int width,
unsigned int x,
unsigned int y)
{
switch (fb_modifier) {
case I915_FORMAT_MOD_Y_TILED:
case I915_FORMAT_MOD_Y_TILED_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
return intel_ytile_get_offset;
case I915_FORMAT_MOD_4_TILED:
case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
case I915_FORMAT_MOD_4_TILED_BMG_CCS:
case I915_FORMAT_MOD_4_TILED_LNL_CCS:
case I915_FORMAT_MOD_X_TILED:
case I915_FORMAT_MOD_Yf_TILED:
case I915_FORMAT_MOD_Yf_TILED_CCS:
default:
/* Not supported yet */
return NULL;
}
}
static int intel_get_scanout_buffer(struct drm_plane *plane,
struct drm_scanout_buffer *sb)
{
@@ -1320,8 +1375,13 @@ static int intel_get_scanout_buffer(struct drm_plane *plane,
} else {
int ret;
/* Can't disable tiling if DPT is in use */
if (intel_fb_uses_dpt(fb))
return -EOPNOTSUPP;
if (intel_fb_uses_dpt(fb)) {
if (fb->format->cpp[0] != 4)
return -EOPNOTSUPP;
intel_fb->panic_tiling = intel_get_tiling_func(fb->modifier);
if (!intel_fb->panic_tiling)
return -EOPNOTSUPP;
}
sb->private = intel_fb;
ret = intel_bo_panic_setup(sb);
if (ret)