@@ -357,15 +357,29 @@ void intel_fb_plane_get_subsampling(int *hsub, int *vsub,
357
357
358
358
static void intel_fb_plane_dims (const struct intel_framebuffer * fb , int color_plane , int * w , int * h )
359
359
{
360
+ struct drm_i915_private * i915 = to_i915 (fb -> base .dev );
360
361
int main_plane = is_ccs_plane (& fb -> base , color_plane ) ?
361
362
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 ;
362
365
int main_hsub , main_vsub ;
363
366
int hsub , vsub ;
364
367
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
+
365
378
intel_fb_plane_get_subsampling (& main_hsub , & main_vsub , & fb -> base , main_plane );
366
379
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 ;
369
383
}
370
384
371
385
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,
547
561
unsigned int height ;
548
562
u32 alignment ;
549
563
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 ))
561
566
alignment = intel_tile_row_size (fb , color_plane );
562
567
else if (fb -> modifier != DRM_FORMAT_MOD_LINEAR )
563
568
alignment = intel_tile_size (i915 );
@@ -688,8 +693,7 @@ bool intel_fb_needs_pot_stride_remap(const struct intel_framebuffer *fb)
688
693
{
689
694
struct drm_i915_private * i915 = to_i915 (fb -> base .dev );
690
695
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 ;
693
697
}
694
698
695
699
static int intel_fb_pitch (const struct intel_framebuffer * fb , int color_plane , unsigned int rotation )
@@ -809,14 +813,16 @@ static unsigned int
809
813
plane_view_dst_stride_tiles (const struct intel_framebuffer * fb , int color_plane ,
810
814
unsigned int pitch_tiles )
811
815
{
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 ;
813
818
/*
814
819
* 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.
816
821
*/
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 {
819
824
return pitch_tiles ;
825
+ }
820
826
}
821
827
822
828
static unsigned int
@@ -852,7 +858,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
852
858
unsigned int tile_height = dims -> tile_height ;
853
859
unsigned int tile_size = intel_tile_size (i915 );
854
860
struct drm_rect r ;
855
- u32 size ;
861
+ u32 size = 0 ;
856
862
857
863
assign_chk_ovf (i915 , remap_info -> offset , obj_offset );
858
864
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
877
883
878
884
color_plane_info -> stride = remap_info -> dst_stride * tile_height ;
879
885
880
- size = remap_info -> dst_stride * remap_info -> width ;
886
+ size + = remap_info -> dst_stride * remap_info -> width ;
881
887
882
888
/* rotate the tile dimensions to match the GTT view */
883
889
swap (tile_width , tile_height );
@@ -886,6 +892,14 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
886
892
887
893
check_array_bounds (i915 , view -> gtt .remapped .plane , color_plane );
888
894
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
+
889
903
assign_chk_ovf (i915 , remap_info -> dst_stride ,
890
904
plane_view_dst_stride_tiles (fb , color_plane , remap_info -> width ));
891
905
@@ -895,7 +909,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
895
909
color_plane_info -> stride = remap_info -> dst_stride * tile_width *
896
910
fb -> base .format -> cpp [color_plane ];
897
911
898
- size = remap_info -> dst_stride * remap_info -> height ;
912
+ size + = remap_info -> dst_stride * remap_info -> height ;
899
913
}
900
914
901
915
/*
@@ -942,10 +956,14 @@ calc_plane_normal_size(const struct intel_framebuffer *fb, int color_plane,
942
956
return tiles ;
943
957
}
944
958
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 )
946
961
{
947
962
memset (view , 0 , sizeof (* view ));
948
963
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 ;
949
967
}
950
968
951
969
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 *
966
984
int i , num_planes = fb -> base .format -> num_planes ;
967
985
unsigned int tile_size = intel_tile_size (i915 );
968
986
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 );
970
988
971
989
drm_WARN_ON (& i915 -> drm ,
972
990
intel_fb_supports_90_270_rotation (fb ) &&
973
991
intel_fb_needs_pot_stride_remap (fb ));
974
992
975
993
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 );
977
995
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 );
979
997
980
998
for (i = 0 ; i < num_planes ; i ++ ) {
981
999
struct fb_plane_view_dims view_dims ;
@@ -1053,7 +1071,7 @@ static void intel_plane_remap_gtt(struct intel_plane_state *plane_state)
1053
1071
unsigned int src_w , src_h ;
1054
1072
u32 gtt_offset = 0 ;
1055
1073
1056
- intel_fb_view_init (& plane_state -> view ,
1074
+ intel_fb_view_init (i915 , & plane_state -> view ,
1057
1075
drm_rotation_90_or_270 (rotation ) ? I915_GGTT_VIEW_ROTATED :
1058
1076
I915_GGTT_VIEW_REMAPPED );
1059
1077
@@ -1158,11 +1176,19 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
1158
1176
1159
1177
tile_width = intel_tile_width_bytes (fb , color_plane );
1160
1178
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 ;
1161
1187
/*
1162
1188
* On TGL the surface stride must be 4 tile aligned, mapped by
1163
1189
* one 64 byte cacheline on the CCS AUX surface.
1164
1190
*/
1165
- if (DISPLAY_VER (dev_priv ) >= 12 )
1191
+ else if (DISPLAY_VER (dev_priv ) >= 12 )
1166
1192
tile_width *= 4 ;
1167
1193
/*
1168
1194
* Display WA #0531: skl,bxt,kbl,glk
@@ -1416,17 +1442,6 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb,
1416
1442
}
1417
1443
}
1418
1444
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
-
1430
1445
fb -> obj [i ] = & obj -> base ;
1431
1446
}
1432
1447
0 commit comments