Commit 672d0751 authored by Imre Deak's avatar Imre Deak

drm/i915: Move intel_get_format_info() to intel_fb.c

Move the function retrieving the format override information for a given
format/modifier to intel_fb.c. We can store a pointer to the format list
in each modifier's descriptor instead of the corresponding switch/case
logic, avoiding the listing of the modifiers twice.

v1: Unchanged.
v2: Handle invalid modifiers in intel_fb_get_format_info() passed from
    userspace. (CI/igt_kms_addfb_basic/addfb25-bad-modifier)
v3: Move lookup_modifier() to the next patch, where it's first used.

Cc: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Cc: Ville Syrjälä <ville.syrjala@linux.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/20211020195138.1841242-3-imre.deak@intel.com
parent e2b83294
......@@ -669,136 +669,6 @@ void intel_add_fb_offsets(int *x, int *y,
*y += state->view.color_plane[color_plane].y;
}
/*
* From the Sky Lake PRM:
* "The Color Control Surface (CCS) contains the compression status of
* the cache-line pairs. The compression state of the cache-line pair
* is specified by 2 bits in the CCS. Each CCS cache-line represents
* an area on the main surface of 16 x16 sets of 128 byte Y-tiled
* cache-line-pairs. CCS is always Y tiled."
*
* Since cache line pairs refers to horizontally adjacent cache lines,
* each cache line in the CCS corresponds to an area of 32x16 cache
* lines on the main surface. Since each pixel is 4 bytes, this gives
* us a ratio of one byte in the CCS for each 8x16 pixels in the
* main surface.
*/
static const struct drm_format_info skl_ccs_formats[] = {
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
};
/*
* Gen-12 compression uses 4 bits of CCS data for each cache line pair in the
* main surface. And each 64B CCS cache line represents an area of 4x1 Y-tiles
* in the main surface. With 4 byte pixels and each Y-tile having dimensions of
* 32x32 pixels, the ratio turns out to 1B in the CCS for every 2x32 pixels in
* the main surface.
*/
static const struct drm_format_info gen12_ccs_formats[] = {
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,
.char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2,
.char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB8888, .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_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_XYUV8888, .num_planes = 2,
.char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 1, .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 },
};
/*
* Same as gen12_ccs_formats[] above, but with additional surface used
* to pass Clear Color information in plane 2 with 64 bits of data.
*/
static const struct drm_format_info gen12_ccs_cc_formats[] = {
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 },
.hsub = 1, .vsub = 1, .has_alpha = true },
};
static const struct drm_format_info *
lookup_format_info(const struct drm_format_info formats[],
int num_formats, u32 format)
{
int i;
for (i = 0; i < num_formats; i++) {
if (formats[i].format == format)
return &formats[i];
}
return NULL;
}
static const struct drm_format_info *
intel_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
{
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_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);
case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC:
return lookup_format_info(gen12_ccs_cc_formats,
ARRAY_SIZE(gen12_ccs_cc_formats),
cmd->pixel_format);
default:
return NULL;
}
}
u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
u32 pixel_format, u64 modifier)
{
......@@ -9538,7 +9408,7 @@ intel_mode_valid_max_plane_size(struct drm_i915_private *dev_priv,
static const struct drm_mode_config_funcs intel_mode_funcs = {
.fb_create = intel_user_framebuffer_create,
.get_format_info = intel_get_format_info,
.get_format_info = intel_fb_get_format_info,
.output_poll_changed = intel_fbdev_output_poll_changed,
.mode_valid = intel_mode_valid,
.atomic_check = intel_atomic_check,
......
......@@ -13,6 +13,99 @@
#define check_array_bounds(i915, a, i) drm_WARN_ON(&(i915)->drm, (i) >= ARRAY_SIZE(a))
/*
* From the Sky Lake PRM:
* "The Color Control Surface (CCS) contains the compression status of
* the cache-line pairs. The compression state of the cache-line pair
* is specified by 2 bits in the CCS. Each CCS cache-line represents
* an area on the main surface of 16 x16 sets of 128 byte Y-tiled
* cache-line-pairs. CCS is always Y tiled."
*
* Since cache line pairs refers to horizontally adjacent cache lines,
* each cache line in the CCS corresponds to an area of 32x16 cache
* lines on the main surface. Since each pixel is 4 bytes, this gives
* us a ratio of one byte in the CCS for each 8x16 pixels in the
* main surface.
*/
static const struct drm_format_info skl_ccs_formats[] = {
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, },
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 2,
.cpp = { 4, 1, }, .hsub = 8, .vsub = 16, .has_alpha = true, },
};
/*
* Gen-12 compression uses 4 bits of CCS data for each cache line pair in the
* main surface. And each 64B CCS cache line represents an area of 4x1 Y-tiles
* in the main surface. With 4 byte pixels and each Y-tile having dimensions of
* 32x32 pixels, the ratio turns out to 1B in the CCS for every 2x32 pixels in
* the main surface.
*/
static const struct drm_format_info gen12_ccs_formats[] = {
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 2,
.char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 2,
.char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB8888, .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_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_XYUV8888, .num_planes = 2,
.char_per_block = { 4, 1 }, .block_w = { 1, 2 }, .block_h = { 1, 1 },
.hsub = 1, .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 },
};
/*
* Same as gen12_ccs_formats[] above, but with additional surface used
* to pass Clear Color information in plane 2 with 64 bits of data.
*/
static const struct drm_format_info gen12_ccs_cc_formats[] = {
{ .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 },
.hsub = 1, .vsub = 1, },
{ .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 },
.hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 3,
.char_per_block = { 4, 1, 0 }, .block_w = { 1, 2, 2 }, .block_h = { 1, 1, 1 },
.hsub = 1, .vsub = 1, .has_alpha = true },
};
struct intel_modifier_desc {
u64 modifier;
struct {
......@@ -21,6 +114,12 @@ struct intel_modifier_desc {
} display_ver;
#define DISPLAY_VER_ALL { 0, -1 }
const struct drm_format_info *formats;
int format_count;
#define FORMAT_OVERRIDE(format_list) \
.formats = format_list, \
.format_count = ARRAY_SIZE(format_list)
u8 is_linear:1;
struct {
......@@ -39,26 +138,36 @@ static const struct intel_modifier_desc intel_modifiers[] = {
.display_ver = { 12, 13 },
.ccs.type = INTEL_CCS_MC,
FORMAT_OVERRIDE(gen12_ccs_formats),
}, {
.modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
.display_ver = { 12, 13 },
.ccs.type = INTEL_CCS_RC,
FORMAT_OVERRIDE(gen12_ccs_formats),
}, {
.modifier = I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC,
.display_ver = { 12, 13 },
.ccs.type = INTEL_CCS_RC_CC,
FORMAT_OVERRIDE(gen12_ccs_cc_formats),
}, {
.modifier = I915_FORMAT_MOD_Yf_TILED_CCS,
.display_ver = { 9, 11 },
.ccs.type = INTEL_CCS_RC,
FORMAT_OVERRIDE(skl_ccs_formats),
}, {
.modifier = I915_FORMAT_MOD_Y_TILED_CCS,
.display_ver = { 9, 11 },
.ccs.type = INTEL_CCS_RC,
FORMAT_OVERRIDE(skl_ccs_formats),
}, {
.modifier = I915_FORMAT_MOD_Yf_TILED,
.display_ver = { 9, 11 },
......@@ -76,6 +185,50 @@ static const struct intel_modifier_desc intel_modifiers[] = {
},
};
static const struct intel_modifier_desc *lookup_modifier_or_null(u64 modifier)
{
int i;
for (i = 0; i < ARRAY_SIZE(intel_modifiers); i++)
if (intel_modifiers[i].modifier == modifier)
return &intel_modifiers[i];
return NULL;
}
static const struct drm_format_info *
lookup_format_info(const struct drm_format_info formats[],
int num_formats, u32 format)
{
int i;
for (i = 0; i < num_formats; i++) {
if (formats[i].format == format)
return &formats[i];
}
return NULL;
}
/**
* intel_fb_get_format_info: Get a modifier specific format information
* @cmd: FB add command structure
*
* Returns:
* Returns the format information for @cmd->pixel_format specific to @cmd->modifier[0],
* or %NULL if the modifier doesn't override the format.
*/
const struct drm_format_info *
intel_fb_get_format_info(const struct drm_mode_fb_cmd2 *cmd)
{
const struct intel_modifier_desc *md = lookup_modifier_or_null(cmd->modifier[0]);
if (!md || !md->formats)
return NULL;
return lookup_format_info(md->formats, md->format_count, cmd->pixel_format);
}
static bool is_ccs_type_modifier(const struct intel_modifier_desc *md, u8 ccs_type)
{
return md->ccs.type & ccs_type;
......
......@@ -36,6 +36,9 @@ u64 *intel_fb_plane_get_modifiers(struct drm_i915_private *i915,
enum intel_plane_caps plane_caps);
bool intel_fb_plane_supports_modifier(struct intel_plane *plane, u64 modifier);
const struct drm_format_info *
intel_fb_get_format_info(const struct drm_mode_fb_cmd2 *cmd);
bool is_surface_linear(const struct drm_framebuffer *fb, int color_plane);
int main_to_ccs_plane(const struct drm_framebuffer *fb, int main_plane);
......
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