Skip to content

Commit a4606d4

Browse files
committed
drm/i915: Add support for FBs requiring a POT stride alignment
An upcoming platform has a restriction that the FB stride must be power-of-two aligned. To support framebuffer layouts that are not in this layout add a logic that pads the tile rows to the POT aligned size. The HW won't read the padding PTEs, so these don't have to point to an allocated address, or even have their valid flag set. So use a NULL PTE instead for instance the scratch page, which is simple and keeps the SG table compact. v2: - Simplify plane_view_dst_stride(). (Ville) - Pass pitch_tiles as unsigned int. v3: - Drop unintentional s/plane_state->rotation/plane_config->rotation/ change. Signed-off-by: Imre Deak <[email protected]> Reviewed-by: Ville Syrjälä <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 6d80f43 commit a4606d4

File tree

7 files changed

+112
-22
lines changed

7 files changed

+112
-22
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info
933933
int i;
934934

935935
for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++)
936-
size += rot_info->plane[i].width * rot_info->plane[i].height;
936+
size += rot_info->plane[i].dst_stride * rot_info->plane[i].width;
937937

938938
return size;
939939
}
@@ -944,7 +944,7 @@ unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info
944944
int i;
945945

946946
for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++)
947-
size += rem_info->plane[i].width * rem_info->plane[i].height;
947+
size += rem_info->plane[i].dst_stride * rem_info->plane[i].height;
948948

949949
return size;
950950
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ struct intel_framebuffer {
128128
/* Params to remap the FB pages and program the plane registers in each view. */
129129
struct intel_fb_view normal_view;
130130
struct intel_fb_view rotated_view;
131+
struct intel_fb_view remapped_view;
131132
};
132133

133134
struct intel_fbdev {

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

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -486,10 +486,17 @@ static bool intel_plane_can_remap(const struct intel_plane_state *plane_state)
486486
return true;
487487
}
488488

489+
static bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb)
490+
{
491+
return false;
492+
}
493+
489494
static int intel_fb_pitch(const struct intel_framebuffer *fb, int color_plane, unsigned int rotation)
490495
{
491496
if (drm_rotation_90_or_270(rotation))
492497
return fb->rotated_view.color_plane[color_plane].stride;
498+
else if (intel_fb_needs_pot_stride_remap(fb))
499+
return fb->remapped_view.color_plane[color_plane].stride;
493500
else
494501
return fb->normal_view.color_plane[color_plane].stride;
495502
}
@@ -597,6 +604,16 @@ plane_view_src_stride_tiles(const struct intel_framebuffer *fb, int color_plane,
597604
dims->tile_width * fb->base.format->cpp[color_plane]);
598605
}
599606

607+
static unsigned int
608+
plane_view_dst_stride_tiles(const struct intel_framebuffer *fb, int color_plane,
609+
unsigned int pitch_tiles)
610+
{
611+
if (intel_fb_needs_pot_stride_remap(fb))
612+
return roundup_pow_of_two(pitch_tiles);
613+
else
614+
return pitch_tiles;
615+
}
616+
600617
static unsigned int
601618
plane_view_width_tiles(const struct intel_framebuffer *fb, int color_plane,
602619
const struct fb_plane_view_dims *dims,
@@ -629,8 +646,8 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
629646
unsigned int tile_width = dims->tile_width;
630647
unsigned int tile_height = dims->tile_height;
631648
unsigned int tile_size = intel_tile_size(i915);
632-
unsigned int pitch_tiles;
633649
struct drm_rect r;
650+
u32 size;
634651

635652
assign_chk_ovf(i915, remap_info->offset, obj_offset);
636653
assign_chk_ovf(i915, remap_info->src_stride, plane_view_src_stride_tiles(fb, color_plane, dims));
@@ -640,6 +657,9 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
640657
if (view->gtt.type == I915_GGTT_VIEW_ROTATED) {
641658
check_array_bounds(i915, view->gtt.rotated.plane, color_plane);
642659

660+
assign_chk_ovf(i915, remap_info->dst_stride,
661+
plane_view_dst_stride_tiles(fb, color_plane, remap_info->height));
662+
643663
/* rotate the x/y offsets to match the GTT view */
644664
drm_rect_init(&r, x, y, dims->width, dims->height);
645665
drm_rect_rotate(&r,
@@ -650,8 +670,9 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
650670
color_plane_info->x = r.x1;
651671
color_plane_info->y = r.y1;
652672

653-
pitch_tiles = remap_info->height;
654-
color_plane_info->stride = pitch_tiles * tile_height;
673+
color_plane_info->stride = remap_info->dst_stride * tile_height;
674+
675+
size = remap_info->dst_stride * remap_info->width;
655676

656677
/* rotate the tile dimensions to match the GTT view */
657678
swap(tile_width, tile_height);
@@ -660,12 +681,16 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
660681

661682
check_array_bounds(i915, view->gtt.remapped.plane, color_plane);
662683

684+
assign_chk_ovf(i915, remap_info->dst_stride,
685+
plane_view_dst_stride_tiles(fb, color_plane, remap_info->width));
686+
663687
color_plane_info->x = x;
664688
color_plane_info->y = y;
665689

666-
pitch_tiles = remap_info->width;
667-
color_plane_info->stride = pitch_tiles * tile_width *
668-
fb->base.format->cpp[color_plane];
690+
color_plane_info->stride = remap_info->dst_stride * tile_width *
691+
fb->base.format->cpp[color_plane];
692+
693+
size = remap_info->dst_stride * remap_info->height;
669694
}
670695

671696
/*
@@ -675,10 +700,10 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
675700
*/
676701
intel_adjust_tile_offset(&color_plane_info->x, &color_plane_info->y,
677702
tile_width, tile_height,
678-
tile_size, pitch_tiles,
703+
tile_size, remap_info->dst_stride,
679704
gtt_offset * tile_size, 0);
680705

681-
return remap_info->width * remap_info->height;
706+
return size;
682707
}
683708

684709
#undef assign_chk_ovf
@@ -723,12 +748,14 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct drm_framebuffer *fb
723748
struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
724749
struct drm_i915_gem_object *obj = intel_fb_obj(fb);
725750
u32 gtt_offset_rotated = 0;
751+
u32 gtt_offset_remapped = 0;
726752
unsigned int max_size = 0;
727753
int i, num_planes = fb->format->num_planes;
728754
unsigned int tile_size = intel_tile_size(i915);
729755

730756
intel_fb_view_init(&intel_fb->normal_view, I915_GGTT_VIEW_NORMAL);
731757
intel_fb_view_init(&intel_fb->rotated_view, I915_GGTT_VIEW_ROTATED);
758+
intel_fb_view_init(&intel_fb->remapped_view, I915_GGTT_VIEW_REMAPPED);
732759

733760
for (i = 0; i < num_planes; i++) {
734761
struct fb_plane_view_dims view_dims;
@@ -776,6 +803,11 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct drm_framebuffer *fb
776803
offset, gtt_offset_rotated, x, y,
777804
&intel_fb->rotated_view);
778805

806+
if (intel_fb_needs_pot_stride_remap(intel_fb))
807+
gtt_offset_remapped += calc_plane_remap_info(intel_fb, i, &view_dims,
808+
offset, gtt_offset_remapped, x, y,
809+
&intel_fb->remapped_view);
810+
779811
size = calc_plane_normal_size(intel_fb, i, &view_dims, x, y);
780812
/* how many tiles in total needed in the bo */
781813
max_size = max(max_size, offset + size);
@@ -859,6 +891,8 @@ void intel_fb_fill_view(const struct intel_framebuffer *fb, unsigned int rotatio
859891
{
860892
if (drm_rotation_90_or_270(rotation))
861893
*view = fb->rotated_view;
894+
else if (intel_fb_needs_pot_stride_remap(fb))
895+
*view = fb->remapped_view;
862896
else
863897
*view = fb->normal_view;
864898
}

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

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,14 +1247,16 @@ void i915_ggtt_resume(struct i915_ggtt *ggtt)
12471247
static struct scatterlist *
12481248
rotate_pages(struct drm_i915_gem_object *obj, unsigned int offset,
12491249
unsigned int width, unsigned int height,
1250-
unsigned int stride,
1250+
unsigned int src_stride, unsigned int dst_stride,
12511251
struct sg_table *st, struct scatterlist *sg)
12521252
{
12531253
unsigned int column, row;
12541254
unsigned int src_idx;
12551255

12561256
for (column = 0; column < width; column++) {
1257-
src_idx = stride * (height - 1) + column + offset;
1257+
unsigned int left;
1258+
1259+
src_idx = src_stride * (height - 1) + column + offset;
12581260
for (row = 0; row < height; row++) {
12591261
st->nents++;
12601262
/*
@@ -1267,8 +1269,25 @@ rotate_pages(struct drm_i915_gem_object *obj, unsigned int offset,
12671269
i915_gem_object_get_dma_address(obj, src_idx);
12681270
sg_dma_len(sg) = I915_GTT_PAGE_SIZE;
12691271
sg = sg_next(sg);
1270-
src_idx -= stride;
1272+
src_idx -= src_stride;
12711273
}
1274+
1275+
left = (dst_stride - height) * I915_GTT_PAGE_SIZE;
1276+
1277+
if (!left)
1278+
continue;
1279+
1280+
st->nents++;
1281+
1282+
/*
1283+
* The DE ignores the PTEs for the padding tiles, the sg entry
1284+
* here is just a conenience to indicate how many padding PTEs
1285+
* to insert at this spot.
1286+
*/
1287+
sg_set_page(sg, NULL, left, 0);
1288+
sg_dma_address(sg) = 0;
1289+
sg_dma_len(sg) = left;
1290+
sg = sg_next(sg);
12721291
}
12731292

12741293
return sg;
@@ -1297,11 +1316,12 @@ intel_rotate_pages(struct intel_rotation_info *rot_info,
12971316
st->nents = 0;
12981317
sg = st->sgl;
12991318

1300-
for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++) {
1319+
for (i = 0 ; i < ARRAY_SIZE(rot_info->plane); i++)
13011320
sg = rotate_pages(obj, rot_info->plane[i].offset,
13021321
rot_info->plane[i].width, rot_info->plane[i].height,
1303-
rot_info->plane[i].src_stride, st, sg);
1304-
}
1322+
rot_info->plane[i].src_stride,
1323+
rot_info->plane[i].dst_stride,
1324+
st, sg);
13051325

13061326
return st;
13071327

@@ -1319,7 +1339,7 @@ intel_rotate_pages(struct intel_rotation_info *rot_info,
13191339
static struct scatterlist *
13201340
remap_pages(struct drm_i915_gem_object *obj, unsigned int offset,
13211341
unsigned int width, unsigned int height,
1322-
unsigned int stride,
1342+
unsigned int src_stride, unsigned int dst_stride,
13231343
struct sg_table *st, struct scatterlist *sg)
13241344
{
13251345
unsigned int row;
@@ -1352,7 +1372,24 @@ remap_pages(struct drm_i915_gem_object *obj, unsigned int offset,
13521372
left -= length;
13531373
}
13541374

1355-
offset += stride - width;
1375+
offset += src_stride - width;
1376+
1377+
left = (dst_stride - width) * I915_GTT_PAGE_SIZE;
1378+
1379+
if (!left)
1380+
continue;
1381+
1382+
st->nents++;
1383+
1384+
/*
1385+
* The DE ignores the PTEs for the padding tiles, the sg entry
1386+
* here is just a conenience to indicate how many padding PTEs
1387+
* to insert at this spot.
1388+
*/
1389+
sg_set_page(sg, NULL, left, 0);
1390+
sg_dma_address(sg) = 0;
1391+
sg_dma_len(sg) = left;
1392+
sg = sg_next(sg);
13561393
}
13571394

13581395
return sg;
@@ -1384,7 +1421,8 @@ intel_remap_pages(struct intel_remapped_info *rem_info,
13841421
for (i = 0 ; i < ARRAY_SIZE(rem_info->plane); i++) {
13851422
sg = remap_pages(obj, rem_info->plane[i].offset,
13861423
rem_info->plane[i].width, rem_info->plane[i].height,
1387-
rem_info->plane[i].src_stride, st, sg);
1424+
rem_info->plane[i].src_stride, rem_info->plane[i].dst_stride,
1425+
st, sg);
13881426
}
13891427

13901428
i915_sg_trim(st);

drivers/gpu/drm/i915/i915_debugfs.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,26 +173,30 @@ i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
173173
break;
174174

175175
case I915_GGTT_VIEW_ROTATED:
176-
seq_printf(m, ", rotated [(%ux%u, stride=%u, offset=%u), (%ux%u, stride=%u, offset=%u)]",
176+
seq_printf(m, ", rotated [(%ux%u, src_stride=%u, dst_stride=%u, offset=%u), (%ux%u, src_stride=%u, dst_stride=%u, offset=%u)]",
177177
vma->ggtt_view.rotated.plane[0].width,
178178
vma->ggtt_view.rotated.plane[0].height,
179179
vma->ggtt_view.rotated.plane[0].src_stride,
180+
vma->ggtt_view.rotated.plane[0].dst_stride,
180181
vma->ggtt_view.rotated.plane[0].offset,
181182
vma->ggtt_view.rotated.plane[1].width,
182183
vma->ggtt_view.rotated.plane[1].height,
183184
vma->ggtt_view.rotated.plane[1].src_stride,
185+
vma->ggtt_view.rotated.plane[1].dst_stride,
184186
vma->ggtt_view.rotated.plane[1].offset);
185187
break;
186188

187189
case I915_GGTT_VIEW_REMAPPED:
188-
seq_printf(m, ", remapped [(%ux%u, stride=%u, offset=%u), (%ux%u, stride=%u, offset=%u)]",
190+
seq_printf(m, ", remapped [(%ux%u, src_stride=%u, dst_stride=%u, offset=%u), (%ux%u, src_stride=%u, dst_stride=%u, offset=%u)]",
189191
vma->ggtt_view.remapped.plane[0].width,
190192
vma->ggtt_view.remapped.plane[0].height,
191193
vma->ggtt_view.remapped.plane[0].src_stride,
194+
vma->ggtt_view.remapped.plane[0].dst_stride,
192195
vma->ggtt_view.remapped.plane[0].offset,
193196
vma->ggtt_view.remapped.plane[1].width,
194197
vma->ggtt_view.remapped.plane[1].height,
195198
vma->ggtt_view.remapped.plane[1].src_stride,
199+
vma->ggtt_view.remapped.plane[1].dst_stride,
196200
vma->ggtt_view.remapped.plane[1].offset);
197201
break;
198202

drivers/gpu/drm/i915/i915_vma_types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ struct intel_remapped_plane_info {
101101
u16 width;
102102
u16 height;
103103
u16 src_stride;
104-
u16 unused_mbz;
104+
u16 dst_stride;
105105
} __packed;
106106

107107
struct intel_remapped_info {

drivers/gpu/drm/i915/selftests/i915_vma.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,15 @@ static int igt_vma_rotate_remap(void *arg)
528528
GEM_BUG_ON(max_offset > max_pages);
529529
max_offset = max_pages - max_offset;
530530

531+
if (!plane_info[0].dst_stride)
532+
plane_info[0].dst_stride = view.type == I915_GGTT_VIEW_ROTATED ?
533+
plane_info[0].height :
534+
plane_info[0].width;
535+
if (!plane_info[1].dst_stride)
536+
plane_info[1].dst_stride = view.type == I915_GGTT_VIEW_ROTATED ?
537+
plane_info[1].height :
538+
plane_info[1].width;
539+
531540
for_each_prime_number_from(plane_info[0].offset, 0, max_offset) {
532541
for_each_prime_number_from(plane_info[1].offset, 0, max_offset) {
533542
struct scatterlist *sg;
@@ -902,6 +911,10 @@ static int igt_vma_remapped_gtt(void *arg)
902911
if (err)
903912
goto out;
904913

914+
if (!plane_info[0].dst_stride)
915+
plane_info[0].dst_stride = *t == I915_GGTT_VIEW_ROTATED ?
916+
p->height : p->width;
917+
905918
vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE);
906919
if (IS_ERR(vma)) {
907920
err = PTR_ERR(vma);

0 commit comments

Comments
 (0)