Skip to content

Commit 116d86d

Browse files
Jocelyn FalempeMaarten Lankhorst
authored andcommitted
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Maarten Lankhorst <[email protected]>
1 parent 31d886b commit 116d86d

File tree

5 files changed

+94
-8
lines changed

5 files changed

+94
-8
lines changed

drivers/gpu/drm/i915/display/intel_display_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ struct intel_framebuffer {
146146

147147
unsigned int min_alignment;
148148
unsigned int vtd_guard;
149+
150+
unsigned int (*panic_tiling)(unsigned int x, unsigned int y, unsigned int width);
149151
};
150152

151153
enum intel_hotplug_state {

drivers/gpu/drm/i915/display/intel_plane.c

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,6 +1272,32 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
12721272
intel_plane_unpin_fb(old_plane_state);
12731273
}
12741274

1275+
/* Handle Y-tiling, only if DPT is enabled (otherwise disabling tiling is easier)
1276+
* All DPT hardware have 128-bytes width tiling, so Y-tile dimension is 32x32
1277+
* pixels for 32bits pixels.
1278+
*/
1279+
#define YTILE_WIDTH 32
1280+
#define YTILE_HEIGHT 32
1281+
#define YTILE_SIZE (YTILE_WIDTH * YTILE_HEIGHT * 4)
1282+
1283+
static unsigned int intel_ytile_get_offset(unsigned int width, unsigned int x, unsigned int y)
1284+
{
1285+
u32 offset;
1286+
unsigned int swizzle;
1287+
unsigned int width_in_blocks = DIV_ROUND_UP(width, 32);
1288+
1289+
/* Block offset */
1290+
offset = ((y / YTILE_HEIGHT) * width_in_blocks + (x / YTILE_WIDTH)) * YTILE_SIZE;
1291+
1292+
x = x % YTILE_WIDTH;
1293+
y = y % YTILE_HEIGHT;
1294+
1295+
/* bit order inside a block is x4 x3 x2 y4 y3 y2 y1 y0 x1 x0 */
1296+
swizzle = (x & 3) | ((y & 0x1f) << 2) | ((x & 0x1c) << 5);
1297+
offset += swizzle * 4;
1298+
return offset;
1299+
}
1300+
12751301
static void intel_panic_flush(struct drm_plane *plane)
12761302
{
12771303
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)
12951321
iplane->disable_tiling(iplane);
12961322
}
12971323

1324+
static unsigned int (*intel_get_tiling_func(u64 fb_modifier))(unsigned int width,
1325+
unsigned int x,
1326+
unsigned int y)
1327+
{
1328+
switch (fb_modifier) {
1329+
case I915_FORMAT_MOD_Y_TILED:
1330+
case I915_FORMAT_MOD_Y_TILED_CCS:
1331+
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
1332+
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
1333+
case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
1334+
return intel_ytile_get_offset;
1335+
case I915_FORMAT_MOD_4_TILED:
1336+
case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS:
1337+
case I915_FORMAT_MOD_4_TILED_DG2_MC_CCS:
1338+
case I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC:
1339+
case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS:
1340+
case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS_CC:
1341+
case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
1342+
case I915_FORMAT_MOD_4_TILED_BMG_CCS:
1343+
case I915_FORMAT_MOD_4_TILED_LNL_CCS:
1344+
case I915_FORMAT_MOD_X_TILED:
1345+
case I915_FORMAT_MOD_Yf_TILED:
1346+
case I915_FORMAT_MOD_Yf_TILED_CCS:
1347+
default:
1348+
/* Not supported yet */
1349+
return NULL;
1350+
}
1351+
}
1352+
12981353
static int intel_get_scanout_buffer(struct drm_plane *plane,
12991354
struct drm_scanout_buffer *sb)
13001355
{
@@ -1320,8 +1375,13 @@ static int intel_get_scanout_buffer(struct drm_plane *plane,
13201375
} else {
13211376
int ret;
13221377
/* Can't disable tiling if DPT is in use */
1323-
if (intel_fb_uses_dpt(fb))
1324-
return -EOPNOTSUPP;
1378+
if (intel_fb_uses_dpt(fb)) {
1379+
if (fb->format->cpp[0] != 4)
1380+
return -EOPNOTSUPP;
1381+
intel_fb->panic_tiling = intel_get_tiling_func(fb->modifier);
1382+
if (!intel_fb->panic_tiling)
1383+
return -EOPNOTSUPP;
1384+
}
13251385
sb->private = intel_fb;
13261386
ret = intel_bo_panic_setup(sb);
13271387
if (ret)

drivers/gpu/drm/i915/display/skl_universal_plane.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2795,15 +2795,22 @@ static void skl_disable_tiling(struct intel_plane *plane)
27952795
{
27962796
struct intel_plane_state *state = to_intel_plane_state(plane->base.state);
27972797
struct intel_display *display = to_intel_display(plane);
2798-
u32 stride = state->view.color_plane[0].scanout_stride / 64;
2798+
const struct drm_framebuffer *fb = state->hw.fb;
27992799
u32 plane_ctl;
28002800

28012801
plane_ctl = intel_de_read(display, PLANE_CTL(plane->pipe, plane->id));
2802-
plane_ctl &= ~PLANE_CTL_TILED_MASK;
28032802

2804-
intel_de_write_fw(display, PLANE_STRIDE(plane->pipe, plane->id),
2805-
PLANE_STRIDE_(stride));
2803+
if (intel_fb_uses_dpt(fb)) {
2804+
/* if DPT is enabled, keep tiling, but disable compression */
2805+
plane_ctl &= ~PLANE_CTL_RENDER_DECOMPRESSION_ENABLE;
2806+
} else {
2807+
/* if DPT is not supported, disable tiling, and update stride */
2808+
u32 stride = state->view.color_plane[0].scanout_stride / 64;
28062809

2810+
plane_ctl &= ~PLANE_CTL_TILED_MASK;
2811+
intel_de_write_fw(display, PLANE_STRIDE(plane->pipe, plane->id),
2812+
PLANE_STRIDE_(stride));
2813+
}
28072814
intel_de_write_fw(display, PLANE_CTL(plane->pipe, plane->id), plane_ctl);
28082815

28092816
intel_de_write_fw(display, PLANE_SURF(plane->pipe, plane->id),

drivers/gpu/drm/i915/gem/i915_gem_pages.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,15 @@ static struct page **i915_gem_object_panic_pages(struct drm_i915_gem_object *obj
400400
return pages;
401401
}
402402

403+
static void i915_gem_object_panic_map_set_pixel(struct drm_scanout_buffer *sb, unsigned int x,
404+
unsigned int y, u32 color)
405+
{
406+
struct intel_framebuffer *fb = (struct intel_framebuffer *)sb->private;
407+
unsigned int offset = fb->panic_tiling(sb->width, x, y);
408+
409+
iosys_map_wr(&sb->map[0], offset, u32, color);
410+
}
411+
403412
/*
404413
* The scanout buffer pages are not mapped, so for each pixel,
405414
* use kmap_local_page_try_from_panic() to map the page, and write the pixel.
@@ -413,7 +422,10 @@ static void i915_gem_object_panic_page_set_pixel(struct drm_scanout_buffer *sb,
413422
struct intel_framebuffer *fb = (struct intel_framebuffer *)sb->private;
414423
struct i915_panic_data *panic = to_i915_panic_data(fb);
415424

416-
offset = y * sb->pitch[0] + x * sb->format->cpp[0];
425+
if (fb->panic_tiling)
426+
offset = fb->panic_tiling(sb->width, x, y);
427+
else
428+
offset = y * sb->pitch[0] + x * sb->format->cpp[0];
417429

418430
new_page = offset >> PAGE_SHIFT;
419431
offset = offset % PAGE_SIZE;
@@ -459,6 +471,8 @@ int i915_gem_object_panic_setup(struct drm_scanout_buffer *sb)
459471
else
460472
iosys_map_set_vaddr(&sb->map[0], ptr);
461473

474+
if (fb->panic_tiling)
475+
sb->set_pixel = i915_gem_object_panic_map_set_pixel;
462476
return 0;
463477
}
464478
if (i915_gem_object_has_struct_page(obj)) {

drivers/gpu/drm/xe/display/intel_bo.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,10 @@ static void xe_panic_page_set_pixel(struct drm_scanout_buffer *sb, unsigned int
104104
unsigned int new_page;
105105
unsigned int offset;
106106

107-
offset = y * sb->pitch[0] + x * sb->format->cpp[0];
107+
if (fb->panic_tiling)
108+
offset = fb->panic_tiling(sb->width, x, y);
109+
else
110+
offset = y * sb->pitch[0] + x * sb->format->cpp[0];
108111

109112
new_page = offset >> PAGE_SHIFT;
110113
offset = offset % PAGE_SIZE;

0 commit comments

Comments
 (0)