drm_format_plane_width_bytes() calculates and returns the number of bytes
for given width of specified format. The calculation uses @cpp
in drm format info for byte-aligned formats. If the format isn't
byte-aligned, @cpp should 0, and the macro pixel information is used.
This avoids bit level rounding.

Use this drm_fb_cma_get_gem_addr() for offset calculation.

Signed-off-by: Hyun Kwon <hyun.k...@xilinx.com>
---
v3
- Update according to member changes
- Use @cpp for byte-aligned formats, and macro-pixel for non byte-aligned ones
- Squash a change in drm_fb_cma_helper.c into this
v2
- This function is added
---
---
 drivers/gpu/drm/drm_fb_cma_helper.c |  3 ++-
 drivers/gpu/drm/drm_fourcc.c        | 35 +++++++++++++++++++++++++++++++++++
 include/drm/drm_fourcc.h            |  2 ++
 3 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c 
b/drivers/gpu/drm/drm_fb_cma_helper.c
index 186d00a..271175e 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -124,7 +124,8 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer 
*fb,
                return 0;
 
        paddr = obj->paddr + fb->offsets[plane];
-       paddr += fb->format->cpp[plane] * (state->src_x >> 16);
+       paddr += drm_format_plane_width_bytes(fb->format, plane,
+                                             state->src_x >> 16);
        paddr += fb->pitches[plane] * (state->src_y >> 16);
 
        return paddr;
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 9c0152d..ed95de2 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -348,3 +348,38 @@ int drm_format_plane_height(int height, uint32_t format, 
int plane)
        return height / info->vsub;
 }
 EXPORT_SYMBOL(drm_format_plane_height);
+
+/**
+ * drm_format_plane_width_bytes - bytes of the given width of the plane
+ * @info: DRM format information
+ * @plane: plane index
+ * @width: width to get the number of bytes
+ *
+ * This returns the number of bytes for given @width and @plane.
+ * The @cpp or macro pixel information should be valid.
+ *
+ * Returns:
+ * The bytes of @width of @plane. 0 for invalid format info.
+ */
+int drm_format_plane_width_bytes(const struct drm_format_info *info,
+                                int plane, int width)
+{
+       if (!info || plane >= info->num_planes)
+               return 0;
+
+       if (info->cpp[plane])
+               return info->cpp[plane] * width;
+
+       if (WARN_ON(!info->bytes_per_macropixel[plane] ||
+                   !info->pixels_per_macropixel[plane])) {
+               struct drm_format_name_buf buf;
+
+               DRM_WARN("Either cpp or macro-pixel info should be valid: %s\n",
+                        drm_get_format_name(info->format, &buf));
+               return 0;
+       }
+
+       return DIV_ROUND_UP(width * info->bytes_per_macropixel[plane],
+                           info->pixels_per_macropixel[plane]);
+}
+EXPORT_SYMBOL(drm_format_plane_width_bytes);
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index ce59329..8158290 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -119,6 +119,8 @@ int drm_format_horz_chroma_subsampling(uint32_t format);
 int drm_format_vert_chroma_subsampling(uint32_t format);
 int drm_format_plane_width(int width, uint32_t format, int plane);
 int drm_format_plane_height(int height, uint32_t format, int plane);
+int drm_format_plane_width_bytes(const struct drm_format_info *info,
+                                int plane, int width);
 const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf 
*buf);
 
 #endif /* __DRM_FOURCC_H__ */
-- 
2.7.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to