drm/i915: Move intel_get_format_info() to intel_fb.c
authorImre Deak <imre.deak@intel.com>
Wed, 20 Oct 2021 19:51:29 +0000 (22:51 +0300)
committerImre Deak <imre.deak@intel.com>
Thu, 21 Oct 2021 18:44:36 +0000 (21:44 +0300)
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: Imre Deak <imre.deak@intel.com>
Reviewed-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211020195138.1841242-3-imre.deak@intel.com
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_fb.c
drivers/gpu/drm/i915/display/intel_fb.h

index 79a7552..86333c0 100644 (file)
@@ -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,
index d42b7a1..42919d2 100644 (file)
 
 #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;
index 0f77e81..97b31c3 100644 (file)
@@ -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);