Skip to content

Commit

Permalink
drm/i915/tgl: Gen-12 display can decompress surfaces compressed by th…
Browse files Browse the repository at this point in the history
…e media engine

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
v5:
- Use format block descriptors to get CCS subsampling calculation right
  everywhere.
- Extend the plane state normal view array to accommodate 4 color planes.
- Use helpers to convert between main and CCS planes.
v6: Add missing packed YUV formats to the MC format list. (Yang)
v7: Align UV planes to tile-row size.

Cc: Nanley G Chery <nanley.g.chery@intel.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Matt Roper <matthew.d.roper@intel.com>
Cc: Yang A Shi <yang.a.shi@intel.com>
Cc: Radhakrishna Sripada <radhakrishna.sripada@intel.com>
Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Radhakrishna Sripada <radhakrishna.sripada@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191231233756.18753-8-imre.deak@intel.com
  • Loading branch information
Dhinakaran Pandiyan authored and Imre Deak committed Jan 7, 2020
1 parent a7007ef commit 2dfbf9d
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 51 deletions.
176 changes: 139 additions & 37 deletions drivers/gpu/drm/i915/display/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -1945,7 +1945,9 @@ static bool is_ccs_plane(const struct drm_framebuffer *fb, int plane)

static bool is_gen12_ccs_modifier(u64 modifier)
{
return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS;
return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;

}

static bool is_gen12_ccs_plane(const struct drm_framebuffer *fb, int plane)
Expand Down Expand Up @@ -1978,8 +1980,7 @@ static int ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane)
}

/* Return either the main plane's CCS or - if not a CCS FB - UV plane */
static int
intel_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane)
int intel_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane)
{
if (is_ccs_modifier(fb->modifier))
return main_to_ccs_plane(fb, main_plane);
Expand Down Expand Up @@ -2021,6 +2022,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
return 128;
/* fall through */
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
if (is_ccs_plane(fb, color_plane))
return 64;
/* fall through */
Expand Down Expand Up @@ -2171,6 +2173,10 @@ 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:
if (is_semiplanar_uv_plane(fb, color_plane))
return intel_tile_row_size(fb, color_plane);
/* Fall-through */
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
return 16 * 1024;
case I915_FORMAT_MOD_Y_TILED_CCS:
Expand Down Expand Up @@ -2574,6 +2580,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;
Expand Down Expand Up @@ -2625,6 +2632,30 @@ static const struct drm_format_info gen12_ccs_formats[] = {
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2,
.char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_YUYV, .num_planes = 2,
.char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_YVYU, .num_planes = 2,
.char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_UYVY, .num_planes = 2,
.char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_VYUY, .num_planes = 2,
.char_per_block = { 2, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 2, .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_NV12, .num_planes = 4,
.char_per_block = { 1, 2, 1, 1 }, .block_w = { 1, 1, 4, 4 }, .block_h = { 1, 1, 1, 1 },
.hsub = 2, .vsub = 2, .is_yuv = true },
{ .format = DRM_FORMAT_P010, .num_planes = 4,
.char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 },
.hsub = 2, .vsub = 2, .is_yuv = true },
{ .format = DRM_FORMAT_P012, .num_planes = 4,
.char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 },
.hsub = 2, .vsub = 2, .is_yuv = true },
{ .format = DRM_FORMAT_P016, .num_planes = 4,
.char_per_block = { 2, 4, 1, 1 }, .block_w = { 1, 1, 2, 2 }, .block_h = { 1, 1, 1, 1 },
.hsub = 2, .vsub = 2, .is_yuv = true },
};

static const struct drm_format_info *
Expand All @@ -2651,6 +2682,7 @@ intel_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
ARRAY_SIZE(skl_ccs_formats),
cmd->pixel_format);
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
return lookup_format_info(gen12_ccs_formats,
ARRAY_SIZE(gen12_ccs_formats),
cmd->pixel_format);
Expand All @@ -2662,6 +2694,7 @@ 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_GEN12_MC_CCS ||
modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
modifier == I915_FORMAT_MOD_Yf_TILED_CCS;
}
Expand Down Expand Up @@ -2735,7 +2768,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
*
Expand All @@ -2745,7 +2778,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
Expand Down Expand Up @@ -3639,6 +3672,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:
Expand Down Expand Up @@ -3697,11 +3731,12 @@ static int icl_max_plane_height(void)
return 4320;
}

static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
int main_x, int main_y, u32 main_offset)
static bool
skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state,
int main_x, int main_y, u32 main_offset,
int ccs_plane)
{
const struct drm_framebuffer *fb = plane_state->hw.fb;
int ccs_plane = main_to_ccs_plane(fb, 0);
int aux_x = plane_state->color_plane[ccs_plane].x;
int aux_y = plane_state->color_plane[ccs_plane].y;
u32 aux_offset = plane_state->color_plane[ccs_plane].offset;
Expand Down Expand Up @@ -3815,7 +3850,8 @@ 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;

Expand Down Expand Up @@ -3848,16 +3884,18 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
{
const struct drm_framebuffer *fb = plane_state->hw.fb;
unsigned int rotation = plane_state->hw.rotation;
int max_width = skl_max_plane_width(fb, 1, rotation);
int uv_plane = 1;
int max_width = skl_max_plane_width(fb, uv_plane, rotation);
int max_height = 4096;
int x = plane_state->uapi.src.x1 >> 17;
int y = plane_state->uapi.src.y1 >> 17;
int w = drm_rect_width(&plane_state->uapi.src) >> 17;
int h = drm_rect_height(&plane_state->uapi.src) >> 17;
u32 offset;

intel_add_fb_offsets(&x, &y, plane_state, 1);
offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 1);
intel_add_fb_offsets(&x, &y, plane_state, uv_plane);
offset = intel_plane_compute_aligned_offset(&x, &y,
plane_state, uv_plane);

/* FIXME not quite sure how/if these apply to the chroma plane */
if (w > max_width || h > max_height) {
Expand All @@ -3866,9 +3904,39 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
return -EINVAL;
}

plane_state->color_plane[1].offset = offset;
plane_state->color_plane[1].x = x;
plane_state->color_plane[1].y = y;
if (is_ccs_modifier(fb->modifier)) {
int ccs_plane = main_to_ccs_plane(fb, uv_plane);
int aux_offset = plane_state->color_plane[ccs_plane].offset;
int alignment = intel_surf_alignment(fb, uv_plane);

if (offset > aux_offset)
offset = intel_plane_adjust_aligned_offset(&x, &y,
plane_state,
uv_plane,
offset,
aux_offset & ~(alignment - 1));

while (!skl_check_main_ccs_coordinates(plane_state, x, y,
offset, ccs_plane)) {
if (offset == 0)
break;

offset = intel_plane_adjust_aligned_offset(&x, &y,
plane_state,
uv_plane,
offset, offset - alignment);
}

if (x != plane_state->color_plane[ccs_plane].x ||
y != plane_state->color_plane[ccs_plane].y) {
DRM_DEBUG_KMS("Unable to find suitable display surface offset due to CCS\n");
return -EINVAL;
}
}

plane_state->color_plane[uv_plane].offset = offset;
plane_state->color_plane[uv_plane].x = x;
plane_state->color_plane[uv_plane].y = y;

return 0;
}
Expand All @@ -3878,21 +3946,40 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
const struct drm_framebuffer *fb = plane_state->hw.fb;
int src_x = plane_state->uapi.src.x1 >> 16;
int src_y = plane_state->uapi.src.y1 >> 16;
int hsub;
int vsub;
int x;
int y;
u32 offset;
int ccs_plane;

for (ccs_plane = 0; ccs_plane < fb->format->num_planes; ccs_plane++) {
int main_hsub, main_vsub;
int hsub, vsub;
int x, y;

intel_fb_plane_get_subsampling(&hsub, &vsub, fb, 1);
x = src_x / hsub;
y = src_y / vsub;
intel_add_fb_offsets(&x, &y, plane_state, 1);
offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 1);
if (!is_ccs_plane(fb, ccs_plane))
continue;

intel_fb_plane_get_subsampling(&main_hsub, &main_vsub, fb,
ccs_to_main_plane(fb, ccs_plane));
intel_fb_plane_get_subsampling(&hsub, &vsub, fb, ccs_plane);

hsub *= main_hsub;
vsub *= main_vsub;
x = src_x / hsub;
y = src_y / vsub;

intel_add_fb_offsets(&x, &y, plane_state, ccs_plane);

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;
offset = intel_plane_compute_aligned_offset(&x, &y,
plane_state,
ccs_plane);

plane_state->color_plane[ccs_plane].offset = offset;
plane_state->color_plane[ccs_plane].x = (x * hsub +
src_x % hsub) /
main_hsub;
plane_state->color_plane[ccs_plane].y = (y * vsub +
src_y % vsub) /
main_vsub;
}

return 0;
}
Expand All @@ -3901,6 +3988,7 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)
{
const struct drm_framebuffer *fb = plane_state->hw.fb;
int ret;
bool needs_aux = false;

ret = intel_plane_compute_gtt(plane_state);
if (ret)
Expand All @@ -3910,22 +3998,32 @@ 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 (is_ccs_modifier(fb->modifier)) {
needs_aux = true;
ret = skl_check_ccs_aux_surface(plane_state);
if (ret)
return ret;
}

if (intel_format_info_is_yuv_semiplanar(fb->format,
fb->modifier)) {
needs_aux = true;
ret = skl_check_nv12_aux_surface(plane_state);
if (ret)
return ret;
} else if (is_ccs_modifier(fb->modifier)) {
ret = skl_check_ccs_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);
Expand Down Expand Up @@ -4515,6 +4613,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:
Expand Down Expand Up @@ -10236,6 +10336,8 @@ skl_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;
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/display/intel_display.h
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ void intel_link_compute_m_n(u16 bpp, int nlanes,
struct intel_link_m_n *m_n,
bool constant_n, bool fec_enable);
bool is_ccs_modifier(u64 modifier);
int intel_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane);
void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv);
u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
u32 pixel_format, u64 modifier);
Expand Down
6 changes: 3 additions & 3 deletions drivers/gpu/drm/i915/display/intel_display_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ struct intel_framebuffer {
/* for each plane in the normal GTT view */
struct {
unsigned int x, y;
} normal[2];
/* for each plane in the rotated GTT view */
} normal[4];
/* for each plane in the rotated GTT view for no-CCS formats */
struct {
unsigned int x, y;
unsigned int pitch; /* pixels */
Expand Down Expand Up @@ -555,7 +555,7 @@ struct intel_plane_state {
*/
u32 stride;
int x, y;
} color_plane[2];
} color_plane[4];

/* plane control register */
u32 ctl;
Expand Down
Loading

0 comments on commit 2dfbf9d

Please sign in to comment.