On Fri, 2019-10-04 at 13:27 -0700, Matt Roper 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@xxxxxxxxx> > > Cc: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > > Cc: Matt Roper <matthew.d.roper@xxxxxxxxx> > > Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@xxxxxxxxx> > > Signed-off-by: Lucas De Marchi <lucas.demarchi@xxxxxxxxx> > > --- > > 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; > > + > > + return color_plane >= fb->format->num_planes / 2; > > +} > > This appears to contradict what you indicated on the modifier patch: > > + * Y-tile widths. For semi-planar formats like NV12, CCS plane follows the > + * Y and UV planes i.e., planes 0 and 2 are used for Y and UV surfaces, > + * planes 1 and 3 for the respective CCS. > > Based on that comment I'd expect something more like (color_plane % 2). I need to update the comment in the modifier patch, thanks for catching this. The major change in this version is for planar formats: planes 2 and 3 will be used for CCS instead of 1 and 3. for packed formats: plane 1 will be used for CCS > > > > + > > 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 }, > > +}; > > Don't we also support media compression on RGB and more packed YUV > formats? I.e., see the matrix on bspec page 49250. > > > + > > 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 */ > > Oh, I see. You're effectively unioning gen12_ccs_formats in with this > fall through. I still thing that winds up being a bit confusing so I'd > at least put a comment up above the mc_ccs_formats table. Although I > also worry that a future platform might allow render compression on some > format that it doesn't support media compression on, which would force > us to decouple the tables at that point. > > Even given the union of the two tables, are we still missing some of the > arrangements of YUV422 (i.e., YVYU, UYVY, and VYUY)? I did not include all the supported formats I wanted to get feedback on the interface for planar formats. I'll add them in the next version. > > > 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)); > > + } > > +} > > + > > +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; > > This also doesn't mention the modifier description comment. So I guess > that comment just needs to be updated, Yeah. > and maybe with a description that > the drm_framebuffer color plane ordering doesn't match the order that > they show up in memory. The color plane ordering is expected to match the surfaces positions in memory. My understanding is that UMD's have the flexibility in their ordering, with the only constraints being 1) CCS must be placed after the corresponding main surface 2) UV must be placed after Y. Thanks for the feedback. -DK > > > + 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; > > + } > > + } > > + > > 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; 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) > > +{ > > + 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@xxxxxxxxxxxxxxxxxxxxx > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx > > _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx