Skip to content

Commit 3d1adc3

Browse files
committed
drm/i915/adlp: Add support for remapping CCS FBs
Add support for remapping CCS FBs on ADL-P to remove the restriction of the power-of-two sized stride and the 2MB surface offset alignment for these FBs. We can only remap the tiles on the main surface, not the tiles on the CCS surface, so userspace has to generate the CCS surface aligning to the POT size padded main surface stride (by programming the AUX pagetable accordingly). For the required AUX pagetable setup, this requires that either the main surface stride is 8 tiles or that the stride is 16 tiles aligned (= 64 kbytes, the area mapped by one AUX PTE). v2: - Init intel_remapped_info::plane_alignment only for remapped views and do this from intel_fb_view_init(). Cc: Juha-Pekka Heikkila <[email protected]> Signed-off-by: Imre Deak <[email protected]> Reviewed-by: Juha-Pekka Heikkila <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 929dd11 commit 3d1adc3

File tree

5 files changed

+89
-47
lines changed

5 files changed

+89
-47
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,8 +899,11 @@ unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info
899899
unsigned int size = 0;
900900
int i;
901901

902-
for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++)
902+
for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) {
903+
if (rem_info->plane_alignment)
904+
size = ALIGN(size, rem_info->plane_alignment);
903905
size += rem_info->plane[i].dst_stride * rem_info->plane[i].height;
906+
}
904907

905908
return size;
906909
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,6 @@ struct intel_fb_view {
103103
* in the rotated and remapped GTT view all no-CCS formats (up to 2
104104
* color planes) are supported.
105105
*
106-
* TODO: add support for CCS formats in the remapped GTT view.
107-
*
108106
* The view information shared by all FB color planes in the FB,
109107
* like dst x/y and src/dst width, is stored separately in
110108
* intel_plane_state.

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

Lines changed: 54 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -357,15 +357,29 @@ void intel_fb_plane_get_subsampling(int *hsub, int *vsub,
357357

358358
static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_plane, int *w, int *h)
359359
{
360+
struct drm_i915_private *i915 = to_i915(fb->base.dev);
360361
int main_plane = is_ccs_plane(&fb->base, color_plane) ?
361362
skl_ccs_to_main_plane(&fb->base, color_plane) : 0;
363+
unsigned int main_width = fb->base.width;
364+
unsigned int main_height = fb->base.height;
362365
int main_hsub, main_vsub;
363366
int hsub, vsub;
364367

368+
/*
369+
* On ADL-P the CCS AUX surface layout always aligns with the
370+
* power-of-two aligned main surface stride. The main surface
371+
* stride in the allocated FB object may not be power-of-two
372+
* sized, in which case it is auto-padded to the POT size.
373+
*/
374+
if (IS_ALDERLAKE_P(i915) && is_ccs_plane(&fb->base, color_plane))
375+
main_width = gen12_aligned_scanout_stride(fb, 0) /
376+
fb->base.format->cpp[0];
377+
365378
intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, &fb->base, main_plane);
366379
intel_fb_plane_get_subsampling(&hsub, &vsub, &fb->base, color_plane);
367-
*w = fb->base.width / main_hsub / hsub;
368-
*h = fb->base.height / main_vsub / vsub;
380+
381+
*w = main_width / main_hsub / hsub;
382+
*h = main_height / main_vsub / vsub;
369383
}
370384

371385
static u32 intel_adjust_tile_offset(int *x, int *y,
@@ -547,17 +561,8 @@ static int intel_fb_offset_to_xy(int *x, int *y,
547561
unsigned int height;
548562
u32 alignment;
549563

550-
/*
551-
* All DPT color planes must be 512*4k aligned (the amount mapped by a
552-
* single DPT page). For ADL_P CCS FBs this only works by requiring
553-
* the allocated offsets to be 2MB aligned. Once supoort to remap
554-
* such FBs is added we can remove this requirement, as then all the
555-
* planes can be remapped to an aligned offset.
556-
*/
557-
if (IS_ALDERLAKE_P(i915) && is_ccs_modifier(fb->modifier))
558-
alignment = 512 * 4096;
559-
else if (DISPLAY_VER(i915) >= 12 &&
560-
is_semiplanar_uv_plane(fb, color_plane))
564+
if (DISPLAY_VER(i915) >= 12 &&
565+
is_semiplanar_uv_plane(fb, color_plane))
561566
alignment = intel_tile_row_size(fb, color_plane);
562567
else if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
563568
alignment = intel_tile_size(i915);
@@ -688,8 +693,7 @@ bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb)
688693
{
689694
struct drm_i915_private *i915 = to_i915(fb->base.dev);
690695

691-
return IS_ALDERLAKE_P(i915) && fb->base.modifier != DRM_FORMAT_MOD_LINEAR &&
692-
!is_ccs_modifier(fb->base.modifier);
696+
return IS_ALDERLAKE_P(i915) && fb->base.modifier != DRM_FORMAT_MOD_LINEAR;
693697
}
694698

695699
static int intel_fb_pitch(const struct intel_framebuffer *fb, int color_plane, unsigned int rotation)
@@ -809,14 +813,16 @@ static unsigned int
809813
plane_view_dst_stride_tiles(const struct intel_framebuffer *fb, int color_plane,
810814
unsigned int pitch_tiles)
811815
{
812-
if (intel_fb_needs_pot_stride_remap(fb))
816+
if (intel_fb_needs_pot_stride_remap(fb)) {
817+
unsigned int min_stride = is_ccs_plane(&fb->base, color_plane) ? 2 : 8;
813818
/*
814819
* ADL_P, the only platform needing a POT stride has a minimum
815-
* of 8 stride tiles.
820+
* of 8 main surface and 2 CCS AUX stride tiles.
816821
*/
817-
return roundup_pow_of_two(max(pitch_tiles, 8u));
818-
else
822+
return roundup_pow_of_two(max(pitch_tiles, min_stride));
823+
} else {
819824
return pitch_tiles;
825+
}
820826
}
821827

822828
static unsigned int
@@ -852,7 +858,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
852858
unsigned int tile_height = dims->tile_height;
853859
unsigned int tile_size = intel_tile_size(i915);
854860
struct drm_rect r;
855-
u32 size;
861+
u32 size = 0;
856862

857863
assign_chk_ovf(i915, remap_info->offset, obj_offset);
858864
assign_chk_ovf(i915, remap_info->src_stride, plane_view_src_stride_tiles(fb, color_plane, dims));
@@ -877,7 +883,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
877883

878884
color_plane_info->stride = remap_info->dst_stride * tile_height;
879885

880-
size = remap_info->dst_stride * remap_info->width;
886+
size += remap_info->dst_stride * remap_info->width;
881887

882888
/* rotate the tile dimensions to match the GTT view */
883889
swap(tile_width, tile_height);
@@ -886,6 +892,14 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
886892

887893
check_array_bounds(i915, view->gtt.remapped.plane, color_plane);
888894

895+
if (view->gtt.remapped.plane_alignment) {
896+
unsigned int aligned_offset = ALIGN(gtt_offset,
897+
view->gtt.remapped.plane_alignment);
898+
899+
size += aligned_offset - gtt_offset;
900+
gtt_offset = aligned_offset;
901+
}
902+
889903
assign_chk_ovf(i915, remap_info->dst_stride,
890904
plane_view_dst_stride_tiles(fb, color_plane, remap_info->width));
891905

@@ -895,7 +909,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
895909
color_plane_info->stride = remap_info->dst_stride * tile_width *
896910
fb->base.format->cpp[color_plane];
897911

898-
size = remap_info->dst_stride * remap_info->height;
912+
size += remap_info->dst_stride * remap_info->height;
899913
}
900914

901915
/*
@@ -942,10 +956,14 @@ calc_plane_normal_size(const struct intel_framebuffer *fb, int color_plane,
942956
return tiles;
943957
}
944958

945-
static void intel_fb_view_init(struct intel_fb_view *view, enum i915_ggtt_view_type view_type)
959+
static void intel_fb_view_init(struct drm_i915_private *i915, struct intel_fb_view *view,
960+
enum i915_ggtt_view_type view_type)
946961
{
947962
memset(view, 0, sizeof(*view));
948963
view->gtt.type = view_type;
964+
965+
if (view_type == I915_GGTT_VIEW_REMAPPED && IS_ALDERLAKE_P(i915))
966+
view->gtt.remapped.plane_alignment = SZ_2M / PAGE_SIZE;
949967
}
950968

951969
bool intel_fb_supports_90_270_rotation(const struct intel_framebuffer *fb)
@@ -966,16 +984,16 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *
966984
int i, num_planes = fb->base.format->num_planes;
967985
unsigned int tile_size = intel_tile_size(i915);
968986

969-
intel_fb_view_init(&fb->normal_view, I915_GGTT_VIEW_NORMAL);
987+
intel_fb_view_init(i915, &fb->normal_view, I915_GGTT_VIEW_NORMAL);
970988

971989
drm_WARN_ON(&i915->drm,
972990
intel_fb_supports_90_270_rotation(fb) &&
973991
intel_fb_needs_pot_stride_remap(fb));
974992

975993
if (intel_fb_supports_90_270_rotation(fb))
976-
intel_fb_view_init(&fb->rotated_view, I915_GGTT_VIEW_ROTATED);
994+
intel_fb_view_init(i915, &fb->rotated_view, I915_GGTT_VIEW_ROTATED);
977995
if (intel_fb_needs_pot_stride_remap(fb))
978-
intel_fb_view_init(&fb->remapped_view, I915_GGTT_VIEW_REMAPPED);
996+
intel_fb_view_init(i915, &fb->remapped_view, I915_GGTT_VIEW_REMAPPED);
979997

980998
for (i = 0; i < num_planes; i++) {
981999
struct fb_plane_view_dims view_dims;
@@ -1053,7 +1071,7 @@ static void intel_plane_remap_gtt(struct intel_plane_state *plane_state)
10531071
unsigned int src_w, src_h;
10541072
u32 gtt_offset = 0;
10551073

1056-
intel_fb_view_init(&plane_state->view,
1074+
intel_fb_view_init(i915, &plane_state->view,
10571075
drm_rotation_90_or_270(rotation) ? I915_GGTT_VIEW_ROTATED :
10581076
I915_GGTT_VIEW_REMAPPED);
10591077

@@ -1158,11 +1176,19 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
11581176

11591177
tile_width = intel_tile_width_bytes(fb, color_plane);
11601178
if (is_ccs_modifier(fb->modifier)) {
1179+
/*
1180+
* On ADL-P the stride must be either 8 tiles or a stride
1181+
* that is aligned to 16 tiles, required by the 16 tiles =
1182+
* 64 kbyte CCS AUX PTE granularity, allowing CCS FBs to be
1183+
* remapped.
1184+
*/
1185+
if (IS_ALDERLAKE_P(dev_priv))
1186+
tile_width *= fb->pitches[0] <= tile_width * 8 ? 8 : 16;
11611187
/*
11621188
* On TGL the surface stride must be 4 tile aligned, mapped by
11631189
* one 64 byte cacheline on the CCS AUX surface.
11641190
*/
1165-
if (DISPLAY_VER(dev_priv) >= 12)
1191+
else if (DISPLAY_VER(dev_priv) >= 12)
11661192
tile_width *= 4;
11671193
/*
11681194
* Display WA #0531: skl,bxt,kbl,glk
@@ -1416,17 +1442,6 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
14161442
}
14171443
}
14181444

1419-
/* TODO: Add POT stride remapping support for CCS formats as well. */
1420-
if (IS_ALDERLAKE_P(dev_priv) &&
1421-
mode_cmd->modifier[i] != DRM_FORMAT_MOD_LINEAR &&
1422-
!intel_fb_needs_pot_stride_remap(intel_fb) &&
1423-
!is_power_of_2(mode_cmd->pitches[i])) {
1424-
drm_dbg_kms(&dev_priv->drm,
1425-
"plane %d pitch (%d) must be power of two for tiled buffers\n",
1426-
i, mode_cmd->pitches[i]);
1427-
goto err;
1428-
}
1429-
14301445
fb->obj[i] = &obj->base;
14311446
}
14321447

drivers/gpu/drm/i915/gt/intel_ggtt.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,13 +1373,28 @@ intel_rotate_pages(struct intel_rotation_info *rot_info,
13731373
}
13741374

13751375
static struct scatterlist *
1376-
remap_pages(struct drm_i915_gem_object *obj, unsigned int offset,
1376+
remap_pages(struct drm_i915_gem_object *obj,
1377+
unsigned int offset, unsigned int alignment_pad,
13771378
unsigned int width, unsigned int height,
13781379
unsigned int src_stride, unsigned int dst_stride,
13791380
struct sg_table *st, struct scatterlist *sg)
13801381
{
13811382
unsigned int row;
13821383

1384+
if (alignment_pad) {
1385+
st->nents++;
1386+
1387+
/*
1388+
* The DE ignores the PTEs for the padding tiles, the sg entry
1389+
* here is just a convenience to indicate how many padding PTEs
1390+
* to insert at this spot.
1391+
*/
1392+
sg_set_page(sg, NULL, alignment_pad * 4096, 0);
1393+
sg_dma_address(sg) = 0;
1394+
sg_dma_len(sg) = alignment_pad * 4096;
1395+
sg = sg_next(sg);
1396+
}
1397+
13831398
for (row = 0; row < height; row++) {
13841399
unsigned int left = width * I915_GTT_PAGE_SIZE;
13851400

@@ -1439,6 +1454,7 @@ intel_remap_pages(struct intel_remapped_info *rem_info,
14391454
struct drm_i915_private *i915 = to_i915(obj->base.dev);
14401455
struct sg_table *st;
14411456
struct scatterlist *sg;
1457+
unsigned int gtt_offset = 0;
14421458
int ret = -ENOMEM;
14431459
int i;
14441460

@@ -1455,10 +1471,19 @@ intel_remap_pages(struct intel_remapped_info *rem_info,
14551471
sg = st->sgl;
14561472

14571473
for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) {
1458-
sg = remap_pages(obj, rem_info->plane[i].offset,
1474+
unsigned int alignment_pad = 0;
1475+
1476+
if (rem_info->plane_alignment)
1477+
alignment_pad = ALIGN(gtt_offset, rem_info->plane_alignment) - gtt_offset;
1478+
1479+
sg = remap_pages(obj,
1480+
rem_info->plane[i].offset, alignment_pad,
14591481
rem_info->plane[i].width, rem_info->plane[i].height,
14601482
rem_info->plane[i].src_stride, rem_info->plane[i].dst_stride,
14611483
st, sg);
1484+
1485+
gtt_offset += alignment_pad +
1486+
rem_info->plane[i].dst_stride * rem_info->plane[i].height;
14621487
}
14631488

14641489
i915_sg_trim(st);

drivers/gpu/drm/i915/i915_vma_types.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,9 @@ struct intel_remapped_plane_info {
105105
} __packed;
106106

107107
struct intel_remapped_info {
108-
struct intel_remapped_plane_info plane[2];
109-
u32 unused_mbz;
108+
struct intel_remapped_plane_info plane[4];
109+
/* in gtt pages */
110+
u32 plane_alignment;
110111
} __packed;
111112

112113
struct intel_rotation_info {
@@ -129,7 +130,7 @@ static inline void assert_i915_gem_gtt_types(void)
129130
{
130131
BUILD_BUG_ON(sizeof(struct intel_rotation_info) != 2 * sizeof(u32) + 8 * sizeof(u16));
131132
BUILD_BUG_ON(sizeof(struct intel_partial_info) != sizeof(u64) + sizeof(unsigned int));
132-
BUILD_BUG_ON(sizeof(struct intel_remapped_info) != 3 * sizeof(u32) + 8 * sizeof(u16));
133+
BUILD_BUG_ON(sizeof(struct intel_remapped_info) != 5 * sizeof(u32) + 16 * sizeof(u16));
133134

134135
/* Check that rotation/remapped shares offsets for simplicity */
135136
BUILD_BUG_ON(offsetof(struct intel_remapped_info, plane[0]) !=

0 commit comments

Comments
 (0)