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.kwon@xxxxxxxxxx> --- 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@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel