drm/i915/adlp/fb: Remove restriction on CCS AUX plane strides
authorImre Deak <imre.deak@intel.com>
Tue, 26 Oct 2021 22:51:05 +0000 (01:51 +0300)
committerImre Deak <imre.deak@intel.com>
Tue, 2 Nov 2021 16:08:04 +0000 (18:08 +0200)
As opposed to other GEN12 platforms ADLP provides a way to program the
stride of CCS surfaces independently of the main surface stride (within
the corresponding limit of the preceding and succeeding power-of-two
values of the main surface stride). Using this HW feature we can remove
the POT stride restriction on CCS surfaces, making the ADLP CCS FB uAPI
(FB modifiers) identical to that of TGL.

The HW makes the CCS stride flexible programming possible by deriving
the stride from the value programmed to the PLANE_STRIDE register. After
that the HW rounds up this value to the next power-of-two value and uses
this for walking the pages of the main surface mapped to GTT/DPT.

To align with the above scheme, introduce a scanout_stride view
parameter which will be programmed to the PLANE_STRIDE register and use
the mapping_stride view param to store the POT aligned value of the
same. By requiring userspace to pass in FBs with a CCS stride that
aligns with the main surface stride (matching the requirement of all
GEN12 platforms), the scanout_stride will be the userspace main surface
stride and the mapping_stride will be the POT rounded value of the same.

Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Cc: Nanley G Chery <nanley.g.chery@intel.com>
Cc: Sameer Lattannavar <sameer.lattannavar@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-8-imre.deak@intel.com
drivers/gpu/drm/i915/display/intel_display_types.h
drivers/gpu/drm/i915/display/intel_fb.c
drivers/gpu/drm/i915/display/skl_universal_plane.c

index 1107cbd93260d80e36c5aab449c2cef307ba398c..a174b0b83640b46646937d4c44656db53c844fff 100644 (file)
@@ -116,6 +116,7 @@ struct intel_fb_view {
                 *   pixels for 90/270 degree rotation
                 */
                unsigned int mapping_stride;
+               unsigned int scanout_stride;
        } color_plane[4];
 };
 
index c19a5f881644830787cd08bc2a60d98b62dc3f3c..c4a743d0913fc817b9fab7f4c1da6b4c547052ff 100644 (file)
@@ -503,35 +503,12 @@ int skl_ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane)
        return ccs_plane - fb->format->num_planes / 2;
 }
 
-static unsigned int gen12_aligned_scanout_stride(const struct intel_framebuffer *fb,
-                                                int color_plane)
-{
-       struct drm_i915_private *i915 = to_i915(fb->base.dev);
-       unsigned int stride = fb->base.pitches[color_plane];
-
-       if (IS_ALDERLAKE_P(i915))
-               return roundup_pow_of_two(max(stride,
-                                             8u * intel_tile_width_bytes(&fb->base, color_plane)));
-
-       return stride;
-}
-
 static unsigned int gen12_ccs_aux_stride(struct intel_framebuffer *fb, int ccs_plane)
 {
-       struct drm_i915_private *i915 = to_i915(fb->base.dev);
        int main_plane = skl_ccs_to_main_plane(&fb->base, ccs_plane);
        unsigned int main_stride = fb->base.pitches[main_plane];
        unsigned int main_tile_width = intel_tile_width_bytes(&fb->base, main_plane);
 
-       /*
-        * On ADL-P the AUX stride must align with a power-of-two aligned main
-        * surface stride. The stride of the allocated main surface object can
-        * be less than this POT stride, which is then autopadded to the POT
-        * size.
-        */
-       if (IS_ALDERLAKE_P(i915))
-               main_stride = gen12_aligned_scanout_stride(fb, main_plane);
-
        return DIV_ROUND_UP(main_stride, 4 * main_tile_width) * 64;
 }
 
@@ -801,7 +778,6 @@ void intel_fb_plane_get_subsampling(int *hsub, int *vsub,
 
 static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_plane, int *w, int *h)
 {
-       struct drm_i915_private *i915 = to_i915(fb->base.dev);
        int main_plane = intel_fb_is_ccs_aux_plane(&fb->base, color_plane) ?
                         skl_ccs_to_main_plane(&fb->base, color_plane) : 0;
        unsigned int main_width = fb->base.width;
@@ -809,16 +785,6 @@ static void intel_fb_plane_dims(const struct intel_framebuffer *fb, int color_pl
        int main_hsub, main_vsub;
        int hsub, vsub;
 
-       /*
-        * On ADL-P the CCS AUX surface layout always aligns with the
-        * power-of-two aligned main surface stride. The main surface
-        * stride in the allocated FB object may not be power-of-two
-        * sized, in which case it is auto-padded to the POT size.
-        */
-       if (IS_ALDERLAKE_P(i915) && intel_fb_is_ccs_aux_plane(&fb->base, color_plane))
-               main_width = gen12_aligned_scanout_stride(fb, 0) /
-                            fb->base.format->cpp[0];
-
        intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, &fb->base, main_plane);
        intel_fb_plane_get_subsampling(&hsub, &vsub, &fb->base, color_plane);
 
@@ -1281,6 +1247,21 @@ plane_view_dst_stride_tiles(const struct intel_framebuffer *fb, int color_plane,
        }
 }
 
+static unsigned int
+plane_view_scanout_stride(const struct intel_framebuffer *fb, int color_plane,
+                         unsigned int tile_width,
+                         unsigned int src_stride_tiles, unsigned int dst_stride_tiles)
+{
+       unsigned int stride_tiles;
+
+       if (IS_ALDERLAKE_P(to_i915(fb->base.dev)))
+               stride_tiles = src_stride_tiles;
+       else
+               stride_tiles = dst_stride_tiles;
+
+       return stride_tiles * tile_width * fb->base.format->cpp[color_plane];
+}
+
 static unsigned int
 plane_view_width_tiles(const struct intel_framebuffer *fb, int color_plane,
                       const struct fb_plane_view_dims *dims,
@@ -1372,6 +1353,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
                color_plane_info->y = r.y1;
 
                color_plane_info->mapping_stride = remap_info->dst_stride * tile_height;
+               color_plane_info->scanout_stride = color_plane_info->mapping_stride;
 
                size += remap_info->dst_stride * remap_info->width;
 
@@ -1395,6 +1377,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
 
                if (remap_info->linear) {
                        color_plane_info->mapping_stride = fb->base.pitches[color_plane];
+                       color_plane_info->scanout_stride = color_plane_info->mapping_stride;
 
                        size += remap_info->size;
                } else {
@@ -1405,6 +1388,10 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p
                        color_plane_info->mapping_stride = dst_stride *
                                                           tile_width *
                                                           fb->base.format->cpp[color_plane];
+                       color_plane_info->scanout_stride =
+                               plane_view_scanout_stride(fb, color_plane, tile_width,
+                                                         remap_info->src_stride,
+                                                         dst_stride);
 
                        size += dst_stride * remap_info->height;
                }
@@ -1530,6 +1517,8 @@ int intel_fill_fb_info(struct drm_i915_private *i915, struct intel_framebuffer *
                fb->normal_view.color_plane[i].x = x;
                fb->normal_view.color_plane[i].y = y;
                fb->normal_view.color_plane[i].mapping_stride = fb->base.pitches[i];
+               fb->normal_view.color_plane[i].scanout_stride =
+                       fb->normal_view.color_plane[i].mapping_stride;
 
                offset = calc_plane_aligned_offset(fb, i, &x, &y);
 
@@ -1675,19 +1664,11 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
 
        tile_width = intel_tile_width_bytes(fb, color_plane);
        if (intel_fb_is_ccs_modifier(fb->modifier)) {
-               /*
-                * On ADL-P the stride must be either 8 tiles or a stride
-                * that is aligned to 16 tiles, required by the 16 tiles =
-                * 64 kbyte CCS AUX PTE granularity, allowing CCS FBs to be
-                * remapped.
-                */
-               if (IS_ALDERLAKE_P(dev_priv))
-                       tile_width *= fb->pitches[0] <= tile_width * 8 ? 8 : 16;
                /*
                 * On TGL the surface stride must be 4 tile aligned, mapped by
                 * one 64 byte cacheline on the CCS AUX surface.
                 */
-               else if (DISPLAY_VER(dev_priv) >= 12)
+               if (DISPLAY_VER(dev_priv) >= 12)
                        tile_width *= 4;
                /*
                 * Display WA #0531: skl,bxt,kbl,glk
index 7795ecd8c0fcdb51656c45a7039ee2764824bedf..91a79b1582c9e7d06abbf609262ae66d75d98cc3 100644 (file)
@@ -589,7 +589,7 @@ static u32 skl_plane_stride(const struct intel_plane_state *plane_state,
 {
        const struct drm_framebuffer *fb = plane_state->hw.fb;
        unsigned int rotation = plane_state->hw.rotation;
-       u32 stride = plane_state->view.color_plane[color_plane].mapping_stride;
+       u32 stride = plane_state->view.color_plane[color_plane].scanout_stride;
 
        if (color_plane >= fb->format->num_planes)
                return 0;