[Intel-gfx] [PATCH v4 9/9] Gen-12 display can decompress surfaces compressed by the media engine.
Dhinakaran Pandiyan
dhinakaran.pandiyan at intel.com
Fri Oct 4 23:54:40 UTC 2019
On Fri, 2019-10-04 at 18:36 +0300, Ville Syrjälä wrote:
> On Thu, Sep 26, 2019 at 03:55:12AM -0700, Dhinakaran Pandiyan wrote:
> > Detect the modifier corresponding to media compression to enable
> > display decompression for YUV and xRGB packed formats. A new modifier is
> > added so that the driver can distinguish between media and render
> > compressed buffers. Unlike render decompression, plane 6 and plane 7 do not
> > support media decompression.
> >
> > v2: Fix checkpatch warnings on code style (Lucas)
> >
> > From DK:
> > Separate modifier array for planes that cannot decompress media (Ville)
> >
> > v3: Support planar formats
> > v4: Switch plane order
> >
> > Cc: Nanley G Chery <nanley.g.chery at intel.com>
> > Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
> > Cc: Matt Roper <matthew.d.roper at intel.com>
> > Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan at intel.com>
> > Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>
> > ---
> > drivers/gpu/drm/i915/display/intel_display.c | 290 +++++++++++++-----
> > .../drm/i915/display/intel_display_types.h | 2 +-
> > drivers/gpu/drm/i915/display/intel_sprite.c | 55 +++-
> > drivers/gpu/drm/i915/i915_reg.h | 1 +
> > 4 files changed, 267 insertions(+), 81 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> > b/drivers/gpu/drm/i915/display/intel_display.c
> > index 8ea55d67442c..df3ebaa167ab 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -1888,6 +1888,22 @@ static void intel_disable_pipe(const struct intel_crtc_state
> > *old_crtc_state)
> > intel_wait_for_pipe_off(old_crtc_state);
> > }
> >
> > +bool is_ccs_modifier(u64 modifier)
> > +{
> > + return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
> > + modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ||
> > + modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
> > + modifier == I915_FORMAT_MOD_Yf_TILED_CCS;
> > +}
> > +
> > +static bool is_ccs_plane(const struct drm_framebuffer *fb, int color_plane)
> > +{
> > + if (!is_ccs_modifier(fb->modifier))
> > + return false;
>
> A comment here could help clarify things for the reader. Eg.:
> /*
> * [0] RGB
> * [1] RGB CCS
> * or
> * [0] Y
> * [1] CbCr
> * [2] Y CCS
> * [3] CbCr CCS
> */
>
Will do.
> > +
> > + return color_plane >= fb->format->num_planes / 2;
> > +}
> > +
> > static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv)
> > {
> > return IS_GEN(dev_priv, 2) ? 2048 : 4096;
> > @@ -1908,11 +1924,13 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int
> > color_plane)
> > else
> > return 512;
> > case I915_FORMAT_MOD_Y_TILED_CCS:
> > - if (color_plane == 1)
> > + if (is_ccs_plane(fb, color_plane))
> > return 128;
> > /* fall through */
> > + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> > + /* fall through */
> > case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
> > - if (color_plane == 1)
> > + if (is_ccs_plane(fb, color_plane))
> > return 64;
> > /* fall through */
> > case I915_FORMAT_MOD_Y_TILED:
> > @@ -1921,7 +1939,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
> > else
> > return 512;
> > case I915_FORMAT_MOD_Yf_TILED_CCS:
> > - if (color_plane == 1)
> > + if (is_ccs_plane(fb, color_plane))
> > return 128;
> > /* fall through */
> > case I915_FORMAT_MOD_Yf_TILED:
> > @@ -1949,8 +1967,9 @@ static unsigned int
> > intel_tile_height(const struct drm_framebuffer *fb, int color_plane)
> > {
> > switch (fb->modifier) {
> > + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> > case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
> > - if (color_plane == 1)
> > + if (is_ccs_plane(fb, color_plane))
> > return 1;
> > /* fall through */
> > default:
> > @@ -2055,6 +2074,7 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
> > if (INTEL_GEN(dev_priv) >= 9)
> > return 256 * 1024;
> > return 0;
> > + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> > case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
> > return 16 * 1024;
> > case I915_FORMAT_MOD_Y_TILED_CCS:
> > @@ -2254,10 +2274,17 @@ static u32 intel_adjust_tile_offset(int *x, int *y,
> > return new_offset;
> > }
> >
> > -static bool is_surface_linear(u64 modifier, int color_plane)
> > +static bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane)
> > {
> > - return modifier == DRM_FORMAT_MOD_LINEAR ||
> > - (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS && color_plane == 1);
> > + switch (fb->modifier) {
> > + case DRM_FORMAT_MOD_LINEAR:
> > + return true;
> > + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
> > + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> > + return is_ccs_plane(fb, color_plane);
> > + default:
> > + return false;
> > + }
> > }
> >
> > static u32 intel_adjust_aligned_offset(int *x, int *y,
> > @@ -2272,7 +2299,7 @@ static u32 intel_adjust_aligned_offset(int *x, int *y,
> >
> > WARN_ON(new_offset > old_offset);
> >
> > - if (!is_surface_linear(fb->modifier, color_plane)) {
> > + if (!is_surface_linear(fb, color_plane)) {
> > unsigned int tile_size, tile_width, tile_height;
> > unsigned int pitch_tiles;
> >
> > @@ -2342,7 +2369,7 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv,
> > if (alignment)
> > alignment--;
> >
> > - if (!is_surface_linear(fb->modifier, color_plane)) {
> > + if (!is_surface_linear(fb, color_plane)) {
> > unsigned int tile_size, tile_width, tile_height;
> > unsigned int tile_rows, tiles, pitch_tiles;
> >
> > @@ -2445,6 +2472,7 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier)
> > case I915_FORMAT_MOD_Y_TILED:
> > case I915_FORMAT_MOD_Y_TILED_CCS:
> > case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
> > + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> > return I915_TILING_Y;
> > default:
> > return I915_TILING_NONE;
> > @@ -2494,6 +2522,13 @@ static const struct drm_format_info gen12_ccs_formats[] = {
> > .cpp = { 4, 1, }, .hsub = 2, .vsub = 32, .has_alpha = true },
> > };
> >
> > +static const struct drm_format_info gen12_mc_ccs_formats[] = {
> > + { .format = DRM_FORMAT_YUYV, .num_planes = 2,
> > + .cpp = { 2, 1, }, .hsub = 4, .vsub = 32, .is_yuv = true },
> > + { .format = DRM_FORMAT_NV12, .num_planes = 4,
> > + .cpp = { 1, 2, 1, 1}, .hsub = 2, .vsub = 2, .is_yuv = true },
> > +};
> > +
> > static const struct drm_format_info *
> > lookup_format_info(const struct drm_format_info formats[],
> > int num_formats, u32 format)
> > @@ -2511,12 +2546,21 @@ lookup_format_info(const struct drm_format_info formats[],
> > static const struct drm_format_info *
> > intel_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
> > {
> > + const struct drm_format_info *info;
> > +
> > switch (cmd->modifier[0]) {
> > case I915_FORMAT_MOD_Y_TILED_CCS:
> > case I915_FORMAT_MOD_Yf_TILED_CCS:
> > return lookup_format_info(skl_ccs_formats,
> > ARRAY_SIZE(skl_ccs_formats),
> > cmd->pixel_format);
> > + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> > + info = lookup_format_info(gen12_mc_ccs_formats,
> > + ARRAY_SIZE(gen12_mc_ccs_formats),
> > + cmd->pixel_format);
> > + if (info)
> > + return info;
> > + /* fall through */
> > case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
> > return lookup_format_info(gen12_ccs_formats,
> > ARRAY_SIZE(gen12_ccs_formats),
> > @@ -2526,13 +2570,6 @@ intel_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
> > }
> > }
> >
> > -bool is_ccs_modifier(u64 modifier)
> > -{
> > - return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
> > - modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
> > - modifier == I915_FORMAT_MOD_Yf_TILED_CCS;
> > -}
> > -
> > u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
> > u32 pixel_format, u64 modifier)
> > {
> > @@ -2576,7 +2613,7 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int
> > color_plane)
> > struct drm_i915_private *dev_priv = to_i915(fb->dev);
> > u32 tile_width;
> >
> > - if (is_surface_linear(fb->modifier, color_plane)) {
> > + if (is_surface_linear(fb, color_plane)) {
> > u32 max_stride = intel_plane_fb_max_stride(dev_priv,
> > fb->format->format,
> > fb->modifier);
> > @@ -2592,7 +2629,7 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int
> > color_plane)
> > }
> >
> > tile_width = intel_tile_width_bytes(fb, color_plane);
> > - if (is_ccs_modifier(fb->modifier) && color_plane == 0) {
> > + if (is_ccs_modifier(fb->modifier)) {
> > /*
> > * Display WA #0531: skl,bxt,kbl,glk
> > *
> > @@ -2602,7 +2639,7 @@ intel_fb_stride_alignment(const struct drm_framebuffer *fb, int
> > color_plane)
> > * require the entire fb to accommodate that to avoid
> > * potential runtime errors at plane configuration time.
> > */
> > - if (IS_GEN(dev_priv, 9) && fb->width > 3840)
> > + if (IS_GEN(dev_priv, 9) && color_plane == 0 && fb->width > 3840)
> > tile_width *= 4;
> > /*
> > * The main surface pitch must be padded to a multiple of four
> > @@ -2682,25 +2719,75 @@ static bool intel_plane_needs_remap(const struct intel_plane_state
> > *plane_state)
> > return stride > max_stride;
> > }
> >
> > +static void
> > +intel_fb_plane_get_subsampling(int *hsub, int *vsub, const struct drm_framebuffer *fb, int
> > color_plane)
> > +{
> > + int i;
> > + static const struct {
> > + u32 format;
> > + int vsub[4];
> > + int hsub[4];
> > + } mc_ccs_subsampling[] = { { .hsub = { 1, 2, 8, 16 },
> > + .vsub = { 1, 2, 32, 32 },
> > + .format = DRM_FORMAT_NV12, },
> > + };
> > +
> > + *hsub = fb->format->hsub;
> > + *vsub = fb->format->vsub;
> > +
> > + if (fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS &&
> > + fb->format->num_planes == 4) {
> > + for (i = 0; i < ARRAY_SIZE(mc_ccs_subsampling); i++) {
> > + if (mc_ccs_subsampling[i].format == fb->format->format) {
> > + *hsub = mc_ccs_subsampling[i].hsub[color_plane];
> > + *vsub = mc_ccs_subsampling[i].vsub[color_plane];
> > + break;
> > + }
> > + }
> > + WARN_ON(i == ARRAY_SIZE(mc_ccs_subsampling));
> > + }
>
> Hmm. I wonder if we could switch over to that block size stuff
> in the format info? As is I don't think framebuffer_check() will
> do the right thing for this stuff.
Thought about it quite a bit (even coded some parts). I wasn't 100% sure if it matches what we need
and had too many questions about it's intended usage. Are block dimensions for each plane
independent of each other? Should relative plane dimensions be taken into account or we just define
the dimensions based on each plane's unit block? Do the block dimensions complement vsub and hsub or
is that an alternative?
In any case, felt it would be better to convert all formats/modifiers to switch to using blocks
together. Thoughts?
-DK
>
> > +}
> > +
> > +static void
> > +intel_fb_plane_dims(int *w, int *h, struct drm_framebuffer *fb, int color_plane)
> > +{
> > + int hsub, vsub;
> > +
> > + intel_fb_plane_get_subsampling(&hsub, &vsub, fb, color_plane);
> > + *w = fb->width/hsub;
> > + *h = fb->height/vsub;
> > +}
> > +
> > static int
> > -intel_fb_check_ccs_xy(struct drm_framebuffer *fb, int x, int y)
> > +intel_fb_check_ccs_xy(struct drm_framebuffer *fb, int aux_plane, int x, int y)
> > {
> > struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > - int hsub = fb->format->hsub;
> > - int vsub = fb->format->vsub;
> > + int hsub, vsub;
> > + int hsub_main, vsub_main;
> > int tile_width, tile_height;
> > int ccs_x, ccs_y;
> > int main_x, main_y;
> > + int main_plane;
> > +
> > + if (!is_ccs_plane(fb, aux_plane))
> > + return 0;
> > +
> > + main_plane = (aux_plane - 1) / 2;
>
> 'aux_plane - num_planes/2' might be a clearer way to write that.
> The num_planes/2 already made an appearance in the is_ccs_plane() thing.
>
> Could also extract this to a small helper to help readability.
Okay.
>
> > + intel_tile_dims(fb, aux_plane, &tile_width, &tile_height);
> > + intel_fb_plane_get_subsampling(&hsub, &vsub, fb, aux_plane);
> > + intel_fb_plane_get_subsampling(&hsub_main, &vsub_main, fb,
> > + main_plane);
> >
> > - intel_tile_dims(fb, 1, &tile_width, &tile_height);
> > + hsub /= hsub_main;
> > + vsub /= vsub_main;
> >
> > tile_width *= hsub;
> > tile_height *= vsub;
> >
> > ccs_x = (x * hsub) % tile_width;
> > ccs_y = (y * vsub) % tile_height;
> > - main_x = intel_fb->normal[0].x % tile_width;
> > - main_y = intel_fb->normal[0].y % tile_height;
> > + main_x = intel_fb->normal[main_plane].x % tile_width;
> > + main_y = intel_fb->normal[main_plane].y % tile_height;
> >
> > /*
> > * CCS doesn't have its own x/y offset register, so the intra CCS tile
> > @@ -2710,8 +2797,8 @@ intel_fb_check_ccs_xy(struct drm_framebuffer *fb, int x, int y)
> > DRM_DEBUG_KMS("Bad CCS x/y (main %d,%d ccs %d,%d) full (main %d,%d ccs %d,%d)\n",
> > main_x, main_y,
> > ccs_x, ccs_y,
> > - intel_fb->normal[0].x,
> > - intel_fb->normal[0].y,
> > + intel_fb->normal[main_plane].x,
> > + intel_fb->normal[main_plane].y,
> > x, y);
> > return -EINVAL;
> > }
> > @@ -2739,8 +2826,7 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
> > int ret;
> >
> > cpp = fb->format->cpp[i];
> > - width = drm_framebuffer_plane_width(fb->width, fb, i);
> > - height = drm_framebuffer_plane_height(fb->height, fb, i);
> > + intel_fb_plane_dims(&width, &height, fb, i);
> >
> > ret = intel_fb_offset_to_xy(&x, &y, fb, i);
> > if (ret) {
> > @@ -2749,11 +2835,9 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
> > return ret;
> > }
> >
> > - if (is_ccs_modifier(fb->modifier) && i == 1) {
> > - ret = intel_fb_check_ccs_xy(fb, x, y);
> > - if (ret)
> > - return ret;
> > - }
> > + ret = intel_fb_check_ccs_xy(fb, i, x, y);
> > + if (ret)
> > + return ret;
> >
> > /*
> > * The fence (if used) is aligned to the start of the object
> > @@ -3371,6 +3455,7 @@ static int skl_max_plane_width(const struct drm_framebuffer *fb,
> > return 5120;
> > case I915_FORMAT_MOD_Y_TILED_CCS:
> > case I915_FORMAT_MOD_Yf_TILED_CCS:
> > + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> > /* FIXME AUX plane? */
> > case I915_FORMAT_MOD_Y_TILED:
> > case I915_FORMAT_MOD_Yf_TILED:
> > @@ -3430,16 +3515,18 @@ static int icl_max_plane_height(void)
> > }
> >
> > static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
> > - int main_x, int main_y, u32 main_offset)
> > + int main_x, int main_y,
> > + u32 main_offset, int aux_plane)
> > {
> > const struct drm_framebuffer *fb = plane_state->base.fb;
> > - int hsub = fb->format->hsub;
> > - int vsub = fb->format->vsub;
> > - int aux_x = plane_state->color_plane[1].x;
> > - int aux_y = plane_state->color_plane[1].y;
> > - u32 aux_offset = plane_state->color_plane[1].offset;
> > - u32 alignment = intel_surf_alignment(fb, 1);
> > -
> > + int hsub;
> > + int vsub;
> > + int aux_x = plane_state->color_plane[aux_plane].x;
> > + int aux_y = plane_state->color_plane[aux_plane].y;
> > + u32 aux_offset = plane_state->color_plane[aux_plane].offset;
> > + u32 alignment = intel_surf_alignment(fb, aux_plane);
> > +
> > + intel_fb_plane_get_subsampling(&hsub, &vsub, fb, aux_plane);
> > while (aux_offset >= main_offset && aux_y <= main_y) {
> > int x, y;
> >
> > @@ -3451,7 +3538,7 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state
> > *plane_state
> >
> > x = aux_x / hsub;
> > y = aux_y / vsub;
> > - aux_offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 1,
> > + aux_offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, aux_plane,
> > aux_offset, aux_offset - alignment);
> > aux_x = x * hsub + aux_x % hsub;
> > aux_y = y * vsub + aux_y % vsub;
> > @@ -3460,9 +3547,9 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state
> > *plane_state
> > if (aux_x != main_x || aux_y != main_y)
> > return false;
> >
> > - plane_state->color_plane[1].offset = aux_offset;
> > - plane_state->color_plane[1].x = aux_x;
> > - plane_state->color_plane[1].y = aux_y;
> > + plane_state->color_plane[aux_plane].offset = aux_offset;
> > + plane_state->color_plane[aux_plane].x = aux_x;
> > + plane_state->color_plane[aux_plane].y = aux_y;
> >
> > return true;
> > }
> > @@ -3478,7 +3565,8 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
> > int h = drm_rect_height(&plane_state->base.src) >> 16;
> > int max_width;
> > int max_height;
> > - u32 alignment, offset, aux_offset = plane_state->color_plane[1].offset;
> > + int aux_plane = fb->format->num_planes / 2;
> > + u32 alignment, offset, aux_offset = plane_state->color_plane[aux_plane].offset;
> >
> > if (INTEL_GEN(dev_priv) >= 11)
> > max_width = icl_max_plane_width(fb, 0, rotation);
> > @@ -3536,7 +3624,9 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
> > * they match with the main surface x/y offsets.
> > */
> > if (is_ccs_modifier(fb->modifier)) {
> > - while (!skl_check_main_ccs_coordinates(plane_state, x, y, offset)) {
> > +
> > + while (!skl_check_main_ccs_coordinates(plane_state, x, y,
> > + offset, aux_plane)) {
> > if (offset == 0)
> > break;
> >
> > @@ -3544,7 +3634,8 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state)
> > offset, offset - alignment);
> > }
> >
> > - if (x != plane_state->color_plane[1].x || y != plane_state->color_plane[1].y) {
> > + if (x != plane_state->color_plane[aux_plane].x ||
> > + y != plane_state->color_plane[aux_plane].y) {
> > DRM_DEBUG_KMS("Unable to find suitable display surface offset due to
> > CCS\n");
> > return -EINVAL;
> > }
> > @@ -3587,6 +3678,41 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state
> > *plane_state)
> > return -EINVAL;
> > }
> >
> > + if (is_ccs_modifier(fb->modifier)) {
> > + int aux_offset = plane_state->color_plane[3].offset;
> > + int alignment = intel_surf_alignment(fb, 1);
> > +
> > + if (offset > aux_offset) {
> > + int hsub, vsub;
> > + int main_x = x, main_y = y;
> > +
> > +
> > + intel_fb_plane_get_subsampling(&hsub, &vsub, fb, 1);
> > + x = main_x / hsub;
> > + y = main_y / vsub;
> > + offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 1,
> > + offset,
> > + aux_offset & ~(alignment - 1));
> > + x = x * hsub + main_x % hsub;
> > + y = y * vsub + main_y % vsub;
> > +
> > + }
> > +
> > + while (!skl_check_main_ccs_coordinates(plane_state, x, y, offset, 3)) {
> > + if (offset == 0)
> > + break;
> > +
> > + offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 1,
> > + offset, offset - alignment);
> > + }
> > +
> > + if (x != plane_state->color_plane[3].x ||
> > + y != plane_state->color_plane[3].y) {
> > + DRM_DEBUG_KMS("Unable to find suitable display surface offset due to
> > CCS\n");
> > + return -EINVAL;
> > + }
>
> Probably time to refactor some of the stuff so we don't have to copy
> paste so much.
>
> > + }
> > +
> > plane_state->color_plane[1].offset = offset;
> > plane_state->color_plane[1].x = x;
> > plane_state->color_plane[1].y = y;
> > @@ -3599,19 +3725,30 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state
> > *plane_state)
> > const struct drm_framebuffer *fb = plane_state->base.fb;
> > int src_x = plane_state->base.src.x1 >> 16;
> > int src_y = plane_state->base.src.y1 >> 16;
> > - int hsub = fb->format->hsub;
> > - int vsub = fb->format->vsub;
> > - int x = src_x / hsub;
> > - int y = src_y / vsub;
> > u32 offset;
> > + int ccs;
> >
> > - intel_add_fb_offsets(&x, &y, plane_state, 1);
> > - offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 1);
> >
> > - plane_state->color_plane[1].offset = offset;
> > - plane_state->color_plane[1].x = x * hsub + src_x % hsub;
> > - plane_state->color_plane[1].y = y * vsub + src_y % vsub;
> > + for (ccs = fb->format->num_planes / 2;
>
> I guess another helper to do the main->aux index calculation would make
> this less magicy.
>
> ccs < fb->format->num_planes; ccs++) {
> > + int hsub, vsub;
> > + int main_hsub, main_vsub;
> > + int x, y;
> > +
> > + intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs);
> > + intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb, (ccs - 1)/ 2);
> > +
> > + hsub /= main_hsub;
> > + vsub /= main_vsub;
> > + x = src_x / hsub;
> > + y = src_y / vsub;
> >
> > + intel_add_fb_offsets(&x, &y, plane_state, ccs);
> > + offset = intel_plane_compute_aligned_offset(&x, &y,
> > + plane_state, ccs);
> > + plane_state->color_plane[ccs].offset = offset;
> > + plane_state->color_plane[ccs].x = x * hsub + src_x % hsub;
> > + plane_state->color_plane[ccs].y = y * vsub + src_y % vsub;
> > + }
> > return 0;
> > }
> >
> > @@ -3619,6 +3756,7 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
> > {
> > const struct drm_framebuffer *fb = plane_state->base.fb;
> > int ret;
> > + bool needs_aux = false;
> >
> > ret = intel_plane_compute_gtt(plane_state);
> > if (ret)
> > @@ -3628,21 +3766,31 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
> > return 0;
> >
> > /*
> > - * Handle the AUX surface first since
> > - * the main surface setup depends on it.
> > + * Handle the AUX surface first since the main surface setup depends on
> > + * it.
> > */
> > - if (drm_format_info_is_yuv_semiplanar(fb->format)) {
> > - ret = skl_check_nv12_aux_surface(plane_state);
> > + if (is_ccs_modifier(fb->modifier)) {
> > + needs_aux = true;
> > + ret = skl_check_ccs_aux_surface(plane_state);
> > if (ret)
> > return ret;
> > - } else if (is_ccs_modifier(fb->modifier)) {
> > - ret = skl_check_ccs_aux_surface(plane_state);
> > + }
> > +
> > + if (drm_format_info_is_yuv_semiplanar(fb->format)) {
> > + needs_aux = true;
> > + ret = skl_check_nv12_aux_surface(plane_state);
> > if (ret)
> > return ret;
> > - } else {
> > - plane_state->color_plane[1].offset = ~0xfff;
> > - plane_state->color_plane[1].x = 0;
> > - plane_state->color_plane[1].y = 0;
> > + }
> > +
> > + if (!needs_aux) {
> > + int i;
> > +
> > + for (i = 1; i < fb->format->num_planes; i++) {
> > + plane_state->color_plane[i].offset = ~0xfff;
> > + plane_state->color_plane[i].x = 0;
> > + plane_state->color_plane[i].y = 0;
> > + }
> > }
> >
> > ret = skl_check_main_surface(plane_state);
> > @@ -4030,7 +4178,7 @@ static unsigned int skl_plane_stride_mult(const struct drm_framebuffer
> > *fb,
> > * The stride is either expressed as a multiple of 64 bytes chunks for
> > * linear buffers or in number of tiles for tiled buffers.
> > */
> > - if (is_surface_linear(fb->modifier, color_plane))
> > + if (is_surface_linear(fb, color_plane))
> > return 64;
> > else if (drm_rotation_90_or_270(rotation))
> > return intel_tile_height(fb, color_plane);
> > @@ -4160,6 +4308,8 @@ static u32 skl_plane_ctl_tiling(u64 fb_modifier)
> > return PLANE_CTL_TILED_Y |
> > PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
> > PLANE_CTL_CLEAR_COLOR_DISABLE;
> > + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> > + return PLANE_CTL_TILED_Y | PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE;
> > case I915_FORMAT_MOD_Yf_TILED:
> > return PLANE_CTL_TILED_YF;
> > case I915_FORMAT_MOD_Yf_TILED_CCS:
> > @@ -9968,6 +10118,8 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
> > fb->modifier = INTEL_GEN(dev_priv) >= 12 ?
> > I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS :
> > I915_FORMAT_MOD_Y_TILED_CCS;
> > + else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
> > + fb->modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
> > else
> > fb->modifier = I915_FORMAT_MOD_Y_TILED;
> > break;
> > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h
> > b/drivers/gpu/drm/i915/display/intel_display_types.h
> > index 976669f01a8c..5998b959225c 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> > @@ -530,7 +530,7 @@ struct intel_plane_state {
> > */
> > u32 stride;
> > int x, y;
> > - } color_plane[2];
> > + } color_plane[4];
> >
> > /* plane control register */
> > u32 ctl;
> > diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c
> > b/drivers/gpu/drm/i915/display/intel_sprite.c
> > index 9b9b41b0fc91..788d0fc8d8ef 100644
> > --- a/drivers/gpu/drm/i915/display/intel_sprite.c
> > +++ b/drivers/gpu/drm/i915/display/intel_sprite.c
> > @@ -532,11 +532,13 @@ skl_program_plane(struct intel_plane *plane,
> > struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> > enum plane_id plane_id = plane->id;
> > enum pipe pipe = plane->pipe;
> > + const struct drm_framebuffer *fb = plane_state->base.fb;
> > + int aux_plane = fb->format->num_planes / 2 + color_plane;
> > const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
> > u32 surf_addr = plane_state->color_plane[color_plane].offset;
> > u32 stride = skl_plane_stride(plane_state, color_plane);
> > - u32 aux_dist = plane_state->color_plane[1].offset - surf_addr;
> > - u32 aux_stride = skl_plane_stride(plane_state, 1);
> > + u32 aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr;
> > + u32 aux_stride = skl_plane_stride(plane_state, aux_plane);
> > int crtc_x = plane_state->base.dst.x1;
> > int crtc_y = plane_state->base.dst.y1;
> > u32 x = plane_state->color_plane[color_plane].x;
> > @@ -544,7 +546,6 @@ skl_program_plane(struct intel_plane *plane,
> > u32 src_w = drm_rect_width(&plane_state->base.src) >> 16;
> > u32 src_h = drm_rect_height(&plane_state->base.src) >> 16;
> > struct intel_plane *linked = plane_state->planar_linked_plane;
> > - const struct drm_framebuffer *fb = plane_state->base.fb;
> > u8 alpha = plane_state->base.alpha >> 8;
> > u32 plane_color_ctl = 0;
> > unsigned long irqflags;
> > @@ -619,8 +620,8 @@ skl_program_plane(struct intel_plane *plane,
> >
> > if (INTEL_GEN(dev_priv) < 11)
> > I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
> > - (plane_state->color_plane[1].y << 16) |
> > - plane_state->color_plane[1].x);
> > + (plane_state->color_plane[aux_plane].y << 16) |
> > + plane_state->color_plane[aux_plane].x);
> >
> > /*
> > * The control register self-arms if the plane was previously
> > @@ -1737,7 +1738,8 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
> > fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
> > fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
> > fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
> > - fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS)) {
> > + fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
> > + fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)) {
> > DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n");
> > return -EINVAL;
> > }
> > @@ -2149,7 +2151,16 @@ static const u64 skl_plane_format_modifiers_ccs[] = {
> > DRM_FORMAT_MOD_INVALID
> > };
> >
> > -static const u64 gen12_plane_format_modifiers_ccs[] = {
> > +static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
> > + I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
> > + I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
> > + I915_FORMAT_MOD_Y_TILED,
> > + I915_FORMAT_MOD_X_TILED,
> > + DRM_FORMAT_MOD_LINEAR,
> > + DRM_FORMAT_MOD_INVALID
> > +};
> > +
> > +static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
> > I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
> > I915_FORMAT_MOD_Y_TILED,
> > I915_FORMAT_MOD_X_TILED,
> > @@ -2305,10 +2316,21 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
> > }
> > }
> >
> > +static bool gen12_plane_supports_mc_ccs(enum plane_id plane_id)
>
> plane_has_foo() is the common idiom.
>
> > +{
> > + return plane_id < PLANE_SPRITE4;
> > +}
> > +
> > static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
> > u32 format, u64 modifier)
> > {
> > + struct intel_plane *plane = to_intel_plane(_plane);
> > +
> > switch (modifier) {
> > + case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
> > + if (!gen12_plane_supports_mc_ccs(plane->id))
> > + return false;
> > + /* fall through */
> > case DRM_FORMAT_MOD_LINEAR:
> > case I915_FORMAT_MOD_X_TILED:
> > case I915_FORMAT_MOD_Y_TILED:
> > @@ -2326,14 +2348,17 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
> > if (is_ccs_modifier(modifier))
> > return true;
> > /* fall through */
> > - case DRM_FORMAT_RGB565:
> > - case DRM_FORMAT_XRGB2101010:
> > - case DRM_FORMAT_XBGR2101010:
> > case DRM_FORMAT_YUYV:
> > case DRM_FORMAT_YVYU:
> > case DRM_FORMAT_UYVY:
> > case DRM_FORMAT_VYUY:
> > + if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
> > + return true;
> > + /* fall through */
> > case DRM_FORMAT_NV12:
> > + case DRM_FORMAT_RGB565:
> > + case DRM_FORMAT_XRGB2101010:
> > + case DRM_FORMAT_XBGR2101010:
> > case DRM_FORMAT_P010:
> > case DRM_FORMAT_P012:
> > case DRM_FORMAT_P016:
> > @@ -2470,6 +2495,14 @@ static const u32 *icl_get_plane_formats(struct drm_i915_private
> > *dev_priv,
> > }
> > }
> >
> > +static const u64 *gen12_get_plane_modifiers(enum plane_id plane_id)
> > +{
> > + if (gen12_plane_supports_mc_ccs(plane_id))
> > + return gen12_plane_format_modifiers_mc_ccs;
> > + else
> > + return gen12_plane_format_modifiers_rc_ccs;
> > +}
> > +
> > static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
> > enum pipe pipe, enum plane_id plane_id)
> > {
> > @@ -2536,7 +2569,7 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv,
> >
> > plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
> > if (INTEL_GEN(dev_priv) >= 12) {
> > - modifiers = gen12_plane_format_modifiers_ccs;
> > + modifiers = gen12_get_plane_modifiers(plane_id);
> > plane_funcs = &gen12_plane_funcs;
> > } else {
> > if (plane->has_ccs)
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index 519cfb0a5c42..02eaef8adac0 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -6697,6 +6697,7 @@ enum {
> > #define PLANE_CTL_TILED_Y (4 << 10)
> > #define PLANE_CTL_TILED_YF (5 << 10)
> > #define PLANE_CTL_FLIP_HORIZONTAL (1 << 8)
> > +#define PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE (1 << 4) /* TGL+ */
> > #define PLANE_CTL_ALPHA_MASK (0x3 << 4) /* Pre-GLK */
> > #define PLANE_CTL_ALPHA_DISABLE (0 << 4)
> > #define PLANE_CTL_ALPHA_SW_PREMULTIPLY (2 << 4)
> > --
> > 2.17.1
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
>
More information about the Intel-gfx
mailing list