The layout of a UBWC framebuffer is only known to the DPU, which computes
it from the framebuffer at atomic check time.  msm_framebuffer_init()
cannot check such a framebuffer against its layout, so it applies the
linear size check instead, which neither matches what the DPU fetches
nor what userspace allocates.

Move the calculation next to mdp_get_format() and make it take the
format and the image size instead of the framebuffer, so that it can be
used before the framebuffer is created.  No functional change.

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c |  84 ++---------------------
 drivers/gpu/drm/msm/disp/mdp_format.c       | 100 ++++++++++++++++++++++++++++
 drivers/gpu/drm/msm/msm_drv.h               |   3 +
 3 files changed, 107 insertions(+), 80 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
index a8e9a69834af..06903325e7e7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
@@ -10,8 +10,6 @@
 #include "dpu_kms.h"
 #include "dpu_formats.h"
 
-#define DPU_UBWC_PLANE_SIZE_ALIGNMENT  4096
-
 /*
  * struct dpu_media_color_map - maps drm format to media format
  * @format: DRM base pixel format
@@ -58,87 +56,13 @@ static int _dpu_format_populate_plane_sizes_ubwc(
                struct drm_framebuffer *fb,
                struct dpu_hw_fmt_layout *layout)
 {
-       bool meta = MSM_FORMAT_IS_UBWC(fmt);
-
-       if (MSM_FORMAT_IS_YUV(fmt)) {
-               unsigned int stride, y_sclines, uv_sclines;
-               unsigned int y_tile_width, y_tile_height;
-               unsigned int y_meta_stride, y_meta_scanlines;
-               unsigned int uv_meta_stride, uv_meta_scanlines;
-
-               if (MSM_FORMAT_IS_DX(fmt)) {
-                       if (fmt->flags & MSM_FORMAT_FLAG_UNPACK_TIGHT) {
-                               /* can't use round_up() here because 192 is 
NPoT */
-                               stride = roundup(fb->width, 192);
-                               stride = round_up(stride * 4 / 3, 256);
-                               y_tile_width = 48;
-                       } else {
-                               stride = round_up(fb->width * 2, 256);
-                               y_tile_width = 32;
-                       }
-
-                       y_sclines = round_up(fb->height, 16);
-                       uv_sclines = round_up((fb->height+1)>>1, 16);
-                       y_tile_height = 4;
-               } else {
-                       stride = round_up(fb->width, 128);
-                       y_tile_width = 32;
-
-                       y_sclines = round_up(fb->height, 32);
-                       uv_sclines = round_up((fb->height+1)>>1, 32);
-                       y_tile_height = 8;
-               }
-
-               layout->plane_pitch[0] = stride;
-               layout->plane_size[0] = round_up(layout->plane_pitch[0] *
-                       y_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
-
-               layout->plane_pitch[1] = stride;
-               layout->plane_size[1] = round_up(layout->plane_pitch[1] *
-                       uv_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
-
-               if (!meta)
-                       return 0;
-
-               y_meta_stride = DIV_ROUND_UP(fb->width, y_tile_width);
-               layout->plane_pitch[2] = round_up(y_meta_stride, 64);
+       mdp_format_ubwc_plane_sizes(fmt, fb->width, fb->height,
+                                   layout->plane_pitch, layout->plane_size);
 
-               y_meta_scanlines = DIV_ROUND_UP(fb->height, y_tile_height);
-               y_meta_scanlines = round_up(y_meta_scanlines, 16);
-               layout->plane_size[2] = round_up(layout->plane_pitch[2] *
-                       y_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
-
-               uv_meta_stride = DIV_ROUND_UP((fb->width+1)>>1, y_tile_width / 
2);
-               layout->plane_pitch[3] = round_up(uv_meta_stride, 64);
-
-               uv_meta_scanlines = DIV_ROUND_UP((fb->height+1)>>1, 
y_tile_height);
-               uv_meta_scanlines = round_up(uv_meta_scanlines, 16);
-               layout->plane_size[3] = round_up(layout->plane_pitch[3] *
-                       uv_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
-       } else {
-               unsigned int rgb_scanlines, rgb_meta_scanlines, rgb_meta_stride;
-
-               layout->plane_pitch[0] = round_up(fb->width * fmt->bpp, 256);
-               rgb_scanlines = round_up(fb->height, 16);
-               layout->plane_size[0] = round_up(layout->plane_pitch[0] *
-                       rgb_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
-
-               if (!meta)
-                       return 0;
-
-               /* RGB metadata is fetched through SRC2, SRC1 stays unused */
+       /* RGB metadata is fetched through SRC2, SRC1 stays unused */
+       if (!MSM_FORMAT_IS_YUV(fmt) && MSM_FORMAT_IS_UBWC(fmt))
                layout->num_planes += 1;
 
-               rgb_meta_stride = DIV_ROUND_UP(fb->width, 16);
-               layout->plane_pitch[2] = round_up(rgb_meta_stride, 64);
-
-               rgb_meta_scanlines = DIV_ROUND_UP(fb->height, 4);
-               rgb_meta_scanlines = round_up(rgb_meta_scanlines, 16);
-
-               layout->plane_size[2] = round_up(layout->plane_pitch[2] *
-                       rgb_meta_scanlines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
-       }
-
        return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/disp/mdp_format.c 
b/drivers/gpu/drm/msm/disp/mdp_format.c
index 33da569eae5e..c0121d709110 100644
--- a/drivers/gpu/drm/msm/disp/mdp_format.c
+++ b/drivers/gpu/drm/msm/disp/mdp_format.c
@@ -650,6 +650,106 @@ const struct msm_format *mdp_get_format(struct msm_kms 
*kms, uint32_t format,
        return NULL;
 }
 
+#define MSM_UBWC_PLANE_SIZE_ALIGNMENT  4096
+
+/**
+ * mdp_format_ubwc_plane_sizes - compute the layout of a UBWC or tiled buffer
+ * @fmt: format, which must use MDP_FETCH_UBWC
+ * @width: image width
+ * @height: image height
+ * @pitch: per-plane pitches
+ * @size: per-plane sizes
+ *
+ * Plane indices follow the hardware: 0 is the Y or RGB data, 1 the CbCr data,
+ * 2 the Y or RGB metadata and 3 the CbCr metadata.  Planes not used by the
+ * format are set to zero.
+ */
+void mdp_format_ubwc_plane_sizes(const struct msm_format *fmt,
+                                unsigned int width, unsigned int height,
+                                u32 pitch[4], u32 size[4])
+{
+       bool meta = MSM_FORMAT_IS_UBWC(fmt);
+
+       memset(pitch, 0, 4 * sizeof(*pitch));
+       memset(size, 0, 4 * sizeof(*size));
+
+       if (MSM_FORMAT_IS_YUV(fmt)) {
+               unsigned int stride, y_sclines, uv_sclines;
+               unsigned int y_tile_width, y_tile_height;
+               unsigned int y_meta_stride, y_meta_scanlines;
+               unsigned int uv_meta_stride, uv_meta_scanlines;
+
+               if (MSM_FORMAT_IS_DX(fmt)) {
+                       if (fmt->flags & MSM_FORMAT_FLAG_UNPACK_TIGHT) {
+                               /* can't use round_up() here because 192 is 
NPoT */
+                               stride = roundup(width, 192);
+                               stride = round_up(stride * 4 / 3, 256);
+                               y_tile_width = 48;
+                       } else {
+                               stride = round_up(width * 2, 256);
+                               y_tile_width = 32;
+                       }
+
+                       y_sclines = round_up(height, 16);
+                       uv_sclines = round_up((height + 1) >> 1, 16);
+                       y_tile_height = 4;
+               } else {
+                       stride = round_up(width, 128);
+                       y_tile_width = 32;
+
+                       y_sclines = round_up(height, 32);
+                       uv_sclines = round_up((height + 1) >> 1, 32);
+                       y_tile_height = 8;
+               }
+
+               pitch[0] = stride;
+               size[0] = round_up(pitch[0] * y_sclines,
+                                  MSM_UBWC_PLANE_SIZE_ALIGNMENT);
+
+               pitch[1] = stride;
+               size[1] = round_up(pitch[1] * uv_sclines,
+                                  MSM_UBWC_PLANE_SIZE_ALIGNMENT);
+
+               if (!meta)
+                       return;
+
+               y_meta_stride = DIV_ROUND_UP(width, y_tile_width);
+               pitch[2] = round_up(y_meta_stride, 64);
+
+               y_meta_scanlines = DIV_ROUND_UP(height, y_tile_height);
+               y_meta_scanlines = round_up(y_meta_scanlines, 16);
+               size[2] = round_up(pitch[2] * y_meta_scanlines,
+                                  MSM_UBWC_PLANE_SIZE_ALIGNMENT);
+
+               uv_meta_stride = DIV_ROUND_UP((width + 1) >> 1, y_tile_width / 
2);
+               pitch[3] = round_up(uv_meta_stride, 64);
+
+               uv_meta_scanlines = DIV_ROUND_UP((height + 1) >> 1, 
y_tile_height);
+               uv_meta_scanlines = round_up(uv_meta_scanlines, 16);
+               size[3] = round_up(pitch[3] * uv_meta_scanlines,
+                                  MSM_UBWC_PLANE_SIZE_ALIGNMENT);
+       } else {
+               unsigned int rgb_scanlines, rgb_meta_scanlines, rgb_meta_stride;
+
+               pitch[0] = round_up(width * fmt->bpp, 256);
+               rgb_scanlines = round_up(height, 16);
+               size[0] = round_up(pitch[0] * rgb_scanlines,
+                                  MSM_UBWC_PLANE_SIZE_ALIGNMENT);
+
+               if (!meta)
+                       return;
+
+               rgb_meta_stride = DIV_ROUND_UP(width, 16);
+               pitch[2] = round_up(rgb_meta_stride, 64);
+
+               rgb_meta_scanlines = DIV_ROUND_UP(height, 4);
+               rgb_meta_scanlines = round_up(rgb_meta_scanlines, 16);
+
+               size[2] = round_up(pitch[2] * rgb_meta_scanlines,
+                                  MSM_UBWC_PLANE_SIZE_ALIGNMENT);
+       }
+}
+
 struct csc_cfg *mdp_get_default_csc_cfg(enum csc_type type)
 {
        if (WARN_ON(type >= CSC_MAX))
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 2840e8a5052d..02fde07eb6f6 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -204,6 +204,9 @@ struct msm_drm_private {
 };
 
 const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, 
uint64_t modifier);
+void mdp_format_ubwc_plane_sizes(const struct msm_format *fmt,
+                                unsigned int width, unsigned int height,
+                                u32 pitch[4], u32 size[4]);
 
 struct msm_pending_timer;
 

-- 
2.47.3

Reply via email to