Commit e6d6f689 authored by Imre Deak's avatar Imre Deak

drm/i915/adlp/fb: Remove restriction on CCS AUX plane strides

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: default avatarImre Deak <imre.deak@intel.com>
Reviewed-by: default avatarJuha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211026225105.2783797-8-imre.deak@intel.com
parent 17749ece
......@@ -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];
};
......
......@@ -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
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment