Hello,
Various pieces of information about DRM formats (number of planes, color depth, chroma subsampling, ...) are scattered across different helper functions in the DRM core. Callers of those functions often need to access more than a single parameter of the format, leading to inefficiencies due to multiple lookups.
This patch series addresses this issue by centralizing all format information in a single data structure (02/15). It reimplements the existing format helper functions based on that structure (03/15) and converts the DRM core code to use the new structure (04/15). The DRM core now WARNs when a driver tries to query information about an unsupported format (05/15).
The second part of the patch series removes the drm_fb_get_bpp_depth() legacy function that shouldn't be used directly by drivers. It modifies all its users to use the appropriate API instead (06/15 to 14/15) and finally merges the function into its only caller in the DRM core (15/15).
The new API is also useful for drivers as shown by the "[PATCH v2 00/20] OMAP DRM fixes and improvements" patch series posted yesterday.
Changes since v2:
- Remove bpp field from drm_format_info structure - Replace all users of drm_fb_get_bpp_depth() with the appropriate API - Merge drm_fb_get_bpp_depth() into its only caller
Changes since v1:
- Move format-related helpers to drm_fourcc.c - Use named initializers for the formats array - WARN when calling drm_format_info() for an unsupported format - Don't drop the drm_format_plane_width() and drm_format_plane_height() helpers
Laurent Pinchart (15): drm: Move format-related helpers to drm_fourcc.c drm: Centralize format information drm: Implement the drm_format_*() helpers as drm_format_info() wrappers drm: Use drm_format_info() in DRM core code drm: WARN when calling drm_format_info() for an unsupported format drm: msm: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() drm: sti: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() drm: hdlcd: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() drm: tilcdc: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() drm: cirrus: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() drm: gma500: Replace drm_fb_get_bpp_depth() with drm_format_info() drm: amdgpu: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() drm: radeon: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp() drm: vmwgfx: Replace drm_fb_get_bpp_depth() with drm_format_info() drm: Don't export the drm_fb_get_bpp_depth() function
Documentation/DocBook/gpu.tmpl | 5 + drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 10 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 3 +- drivers/gpu/drm/arm/hdlcd_crtc.c | 5 +- drivers/gpu/drm/cirrus/cirrus_fbdev.c | 6 +- drivers/gpu/drm/cirrus/cirrus_main.c | 4 +- drivers/gpu/drm/drm_crtc.c | 389 +------------------------------ drivers/gpu/drm/drm_crtc_helper.c | 14 +- drivers/gpu/drm/drm_fb_cma_helper.c | 23 +- drivers/gpu/drm/drm_fourcc.c | 280 ++++++++++++++++++++++ drivers/gpu/drm/gma500/framebuffer.c | 20 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 6 +- drivers/gpu/drm/radeon/radeon_fb.c | 14 +- drivers/gpu/drm/radeon/radeon_gem.c | 3 +- drivers/gpu/drm/sti/sti_gdp.c | 6 +- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 23 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 12 +- include/drm/drmP.h | 1 + include/drm/drm_crtc.h | 9 - include/drm/drm_fourcc.h | 56 +++++ 21 files changed, 437 insertions(+), 454 deletions(-) create mode 100644 drivers/gpu/drm/drm_fourcc.c create mode 100644 include/drm/drm_fourcc.h
The drm_crtc.c file is a mess, making the ABI documentation confusing since all functions are in the same bag. Split the format-related helpers to a new drm_fourcc.c file.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- Documentation/DocBook/gpu.tmpl | 5 + drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_crtc.c | 289 ------------------------------------- drivers/gpu/drm/drm_fourcc.c | 320 +++++++++++++++++++++++++++++++++++++++++ include/drm/drmP.h | 1 + include/drm/drm_crtc.h | 9 -- include/drm/drm_fourcc.h | 37 +++++ 7 files changed, 364 insertions(+), 299 deletions(-) create mode 100644 drivers/gpu/drm/drm_fourcc.c create mode 100644 include/drm/drm_fourcc.h
diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl index 7586bf75f62e..d32363cb1ff1 100644 --- a/Documentation/DocBook/gpu.tmpl +++ b/Documentation/DocBook/gpu.tmpl @@ -1656,6 +1656,11 @@ void intel_crt_init(struct drm_device *dev) !Edrivers/gpu/drm/drm_rect.c </sect2> <sect2> + <title>Formats Utilities Reference</title> +!Iinclude/drm/drm_fourcc.h +!Edrivers/gpu/drm/drm_fourcc.c + </sect2> + <sect2> <title>Flip-work Helper Reference</title> !Pinclude/drm/drm_flip_work.h flip utils !Iinclude/drm/drm_flip_work.h diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index be43afb08c69..aa24af35c068 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -8,7 +8,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ drm_lock.o drm_memory.o drm_drv.o drm_vm.o \ drm_scatter.o drm_pci.o \ drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \ - drm_crtc.o drm_modes.o drm_edid.o \ + drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \ drm_info.o drm_debugfs.o drm_encoder_slave.o \ drm_trace_points.o drm_global.o drm_prime.o \ drm_rect.o drm_vma_manager.o drm_flip_work.o \ diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 0e3cc66aa8b7..e5369529af06 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -239,37 +239,6 @@ const char *drm_get_subpixel_order_name(enum subpixel_order order) } EXPORT_SYMBOL(drm_get_subpixel_order_name);
-static char printable_char(int c) -{ - return isascii(c) && isprint(c) ? c : '?'; -} - -/** - * drm_get_format_name - return a string for drm fourcc format - * @format: format to compute name of - * - * Note that the buffer used by this function is globally shared and owned by - * the function itself. - * - * FIXME: This isn't really multithreading safe. - */ -const char *drm_get_format_name(uint32_t format) -{ - static char buf[32]; - - snprintf(buf, sizeof(buf), - "%c%c%c%c %s-endian (0x%08x)", - printable_char(format & 0xff), - printable_char((format >> 8) & 0xff), - printable_char((format >> 16) & 0xff), - printable_char((format >> 24) & 0x7f), - format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little", - format); - - return buf; -} -EXPORT_SYMBOL(drm_get_format_name); - /* * Internal function to assign a slot in the object idr and optionally * register the object into the idr. @@ -5544,264 +5513,6 @@ int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, }
/** - * drm_fb_get_bpp_depth - get the bpp/depth values for format - * @format: pixel format (DRM_FORMAT_*) - * @depth: storage for the depth value - * @bpp: storage for the bpp value - * - * This only supports RGB formats here for compat with code that doesn't use - * pixel formats directly yet. - */ -void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, - int *bpp) -{ - switch (format) { - case DRM_FORMAT_C8: - case DRM_FORMAT_RGB332: - case DRM_FORMAT_BGR233: - *depth = 8; - *bpp = 8; - break; - case DRM_FORMAT_XRGB1555: - case DRM_FORMAT_XBGR1555: - case DRM_FORMAT_RGBX5551: - case DRM_FORMAT_BGRX5551: - case DRM_FORMAT_ARGB1555: - case DRM_FORMAT_ABGR1555: - case DRM_FORMAT_RGBA5551: - case DRM_FORMAT_BGRA5551: - *depth = 15; - *bpp = 16; - break; - case DRM_FORMAT_RGB565: - case DRM_FORMAT_BGR565: - *depth = 16; - *bpp = 16; - break; - case DRM_FORMAT_RGB888: - case DRM_FORMAT_BGR888: - *depth = 24; - *bpp = 24; - break; - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_RGBX8888: - case DRM_FORMAT_BGRX8888: - *depth = 24; - *bpp = 32; - break; - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_RGBX1010102: - case DRM_FORMAT_BGRX1010102: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_RGBA1010102: - case DRM_FORMAT_BGRA1010102: - *depth = 30; - *bpp = 32; - break; - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_RGBA8888: - case DRM_FORMAT_BGRA8888: - *depth = 32; - *bpp = 32; - break; - default: - DRM_DEBUG_KMS("unsupported pixel format %s\n", - drm_get_format_name(format)); - *depth = 0; - *bpp = 0; - break; - } -} -EXPORT_SYMBOL(drm_fb_get_bpp_depth); - -/** - * drm_format_num_planes - get the number of planes for format - * @format: pixel format (DRM_FORMAT_*) - * - * Returns: - * The number of planes used by the specified pixel format. - */ -int drm_format_num_planes(uint32_t format) -{ - switch (format) { - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV444: - case DRM_FORMAT_YVU444: - return 3; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_NV24: - case DRM_FORMAT_NV42: - return 2; - default: - return 1; - } -} -EXPORT_SYMBOL(drm_format_num_planes); - -/** - * drm_format_plane_cpp - determine the bytes per pixel value - * @format: pixel format (DRM_FORMAT_*) - * @plane: plane index - * - * Returns: - * The bytes per pixel value for the specified plane. - */ -int drm_format_plane_cpp(uint32_t format, int plane) -{ - unsigned int depth; - int bpp; - - if (plane >= drm_format_num_planes(format)) - return 0; - - switch (format) { - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - return 2; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_NV24: - case DRM_FORMAT_NV42: - return plane ? 2 : 1; - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV444: - case DRM_FORMAT_YVU444: - return 1; - default: - drm_fb_get_bpp_depth(format, &depth, &bpp); - return bpp >> 3; - } -} -EXPORT_SYMBOL(drm_format_plane_cpp); - -/** - * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor - * @format: pixel format (DRM_FORMAT_*) - * - * Returns: - * The horizontal chroma subsampling factor for the - * specified pixel format. - */ -int drm_format_horz_chroma_subsampling(uint32_t format) -{ - switch (format) { - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - return 4; - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - return 2; - default: - return 1; - } -} -EXPORT_SYMBOL(drm_format_horz_chroma_subsampling); - -/** - * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor - * @format: pixel format (DRM_FORMAT_*) - * - * Returns: - * The vertical chroma subsampling factor for the - * specified pixel format. - */ -int drm_format_vert_chroma_subsampling(uint32_t format) -{ - switch (format) { - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - return 4; - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - return 2; - default: - return 1; - } -} -EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); - -/** - * drm_format_plane_width - width of the plane given the first plane - * @width: width of the first plane - * @format: pixel format - * @plane: plane index - * - * Returns: - * The width of @plane, given that the width of the first plane is @width. - */ -int drm_format_plane_width(int width, uint32_t format, int plane) -{ - if (plane >= drm_format_num_planes(format)) - return 0; - - if (plane == 0) - return width; - - return width / drm_format_horz_chroma_subsampling(format); -} -EXPORT_SYMBOL(drm_format_plane_width); - -/** - * drm_format_plane_height - height of the plane given the first plane - * @height: height of the first plane - * @format: pixel format - * @plane: plane index - * - * Returns: - * The height of @plane, given that the height of the first plane is @height. - */ -int drm_format_plane_height(int height, uint32_t format, int plane) -{ - if (plane >= drm_format_num_planes(format)) - return 0; - - if (plane == 0) - return height; - - return height / drm_format_vert_chroma_subsampling(format); -} -EXPORT_SYMBOL(drm_format_plane_height); - -/** * drm_rotation_simplify() - Try to simplify the rotation * @rotation: Rotation to be simplified * @supported_rotations: Supported rotations diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c new file mode 100644 index 000000000000..0645c85d5f95 --- /dev/null +++ b/drivers/gpu/drm/drm_fourcc.c @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2016 Laurent Pinchart laurent.pinchart@ideasonboard.com + * + * DRM core format related functions + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include <linux/bug.h> +#include <linux/ctype.h> +#include <linux/export.h> +#include <linux/kernel.h> + +#include <drm/drmP.h> +#include <drm/drm_fourcc.h> + +static char printable_char(int c) +{ + return isascii(c) && isprint(c) ? c : '?'; +} + +/** + * drm_get_format_name - return a string for drm fourcc format + * @format: format to compute name of + * + * Note that the buffer used by this function is globally shared and owned by + * the function itself. + * + * FIXME: This isn't really multithreading safe. + */ +const char *drm_get_format_name(uint32_t format) +{ + static char buf[32]; + + snprintf(buf, sizeof(buf), + "%c%c%c%c %s-endian (0x%08x)", + printable_char(format & 0xff), + printable_char((format >> 8) & 0xff), + printable_char((format >> 16) & 0xff), + printable_char((format >> 24) & 0x7f), + format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little", + format); + + return buf; +} +EXPORT_SYMBOL(drm_get_format_name); + +/** + * drm_fb_get_bpp_depth - get the bpp/depth values for format + * @format: pixel format (DRM_FORMAT_*) + * @depth: storage for the depth value + * @bpp: storage for the bpp value + * + * This only supports RGB formats here for compat with code that doesn't use + * pixel formats directly yet. + */ +void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, + int *bpp) +{ + switch (format) { + case DRM_FORMAT_C8: + case DRM_FORMAT_RGB332: + case DRM_FORMAT_BGR233: + *depth = 8; + *bpp = 8; + break; + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_RGBX5551: + case DRM_FORMAT_BGRX5551: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_BGRA5551: + *depth = 15; + *bpp = 16; + break; + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: + *depth = 16; + *bpp = 16; + break; + case DRM_FORMAT_RGB888: + case DRM_FORMAT_BGR888: + *depth = 24; + *bpp = 24; + break; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRX8888: + *depth = 24; + *bpp = 32; + break; + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_BGRX1010102: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_BGRA1010102: + *depth = 30; + *bpp = 32; + break; + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_BGRA8888: + *depth = 32; + *bpp = 32; + break; + default: + DRM_DEBUG_KMS("unsupported pixel format %s\n", + drm_get_format_name(format)); + *depth = 0; + *bpp = 0; + break; + } +} +EXPORT_SYMBOL(drm_fb_get_bpp_depth); + +/** + * drm_format_num_planes - get the number of planes for format + * @format: pixel format (DRM_FORMAT_*) + * + * Returns: + * The number of planes used by the specified pixel format. + */ +int drm_format_num_planes(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_YUV410: + case DRM_FORMAT_YVU410: + case DRM_FORMAT_YUV411: + case DRM_FORMAT_YVU411: + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: + return 3; + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV61: + case DRM_FORMAT_NV24: + case DRM_FORMAT_NV42: + return 2; + default: + return 1; + } +} +EXPORT_SYMBOL(drm_format_num_planes); + +/** + * drm_format_plane_cpp - determine the bytes per pixel value + * @format: pixel format (DRM_FORMAT_*) + * @plane: plane index + * + * Returns: + * The bytes per pixel value for the specified plane. + */ +int drm_format_plane_cpp(uint32_t format, int plane) +{ + unsigned int depth; + int bpp; + + if (plane >= drm_format_num_planes(format)) + return 0; + + switch (format) { + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YVYU: + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + return 2; + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV61: + case DRM_FORMAT_NV24: + case DRM_FORMAT_NV42: + return plane ? 2 : 1; + case DRM_FORMAT_YUV410: + case DRM_FORMAT_YVU410: + case DRM_FORMAT_YUV411: + case DRM_FORMAT_YVU411: + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU444: + return 1; + default: + drm_fb_get_bpp_depth(format, &depth, &bpp); + return bpp >> 3; + } +} +EXPORT_SYMBOL(drm_format_plane_cpp); + +/** + * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor + * @format: pixel format (DRM_FORMAT_*) + * + * Returns: + * The horizontal chroma subsampling factor for the + * specified pixel format. + */ +int drm_format_horz_chroma_subsampling(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_YUV411: + case DRM_FORMAT_YVU411: + case DRM_FORMAT_YUV410: + case DRM_FORMAT_YVU410: + return 4; + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YVYU: + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV61: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YVU420: + return 2; + default: + return 1; + } +} +EXPORT_SYMBOL(drm_format_horz_chroma_subsampling); + +/** + * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor + * @format: pixel format (DRM_FORMAT_*) + * + * Returns: + * The vertical chroma subsampling factor for the + * specified pixel format. + */ +int drm_format_vert_chroma_subsampling(uint32_t format) +{ + switch (format) { + case DRM_FORMAT_YUV410: + case DRM_FORMAT_YVU410: + return 4; + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YVU420: + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV21: + return 2; + default: + return 1; + } +} +EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); + +/** + * drm_format_plane_width - width of the plane given the first plane + * @width: width of the first plane + * @format: pixel format + * @plane: plane index + * + * Returns: + * The width of @plane, given that the width of the first plane is @width. + */ +int drm_format_plane_width(int width, uint32_t format, int plane) +{ + if (plane >= drm_format_num_planes(format)) + return 0; + + if (plane == 0) + return width; + + return width / drm_format_horz_chroma_subsampling(format); +} +EXPORT_SYMBOL(drm_format_plane_width); + +/** + * drm_format_plane_height - height of the plane given the first plane + * @height: height of the first plane + * @format: pixel format + * @plane: plane index + * + * Returns: + * The height of @plane, given that the height of the first plane is @height. + */ +int drm_format_plane_height(int height, uint32_t format, int plane) +{ + if (plane >= drm_format_num_planes(format)) + return 0; + + if (plane == 0) + return height; + + return height / drm_format_vert_chroma_subsampling(format); +} +EXPORT_SYMBOL(drm_format_plane_height); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 84f1a8eefbdb..c8879057084e 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -66,6 +66,7 @@
#include <drm/drm_agpsupport.h> #include <drm/drm_crtc.h> +#include <drm/drm_fourcc.h> #include <drm/drm_global.h> #include <drm/drm_hashtab.h> #include <drm/drm_mem_util.h> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index d1559cd04e3d..1b80c0268d8f 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -2540,15 +2540,6 @@ extern int drm_mode_plane_set_obj_prop(struct drm_plane *plane, extern int drm_mode_atomic_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, - int *bpp); -extern int drm_format_num_planes(uint32_t format); -extern int drm_format_plane_cpp(uint32_t format, int plane); -extern int drm_format_horz_chroma_subsampling(uint32_t format); -extern int drm_format_vert_chroma_subsampling(uint32_t format); -extern int drm_format_plane_width(int width, uint32_t format, int plane); -extern int drm_format_plane_height(int height, uint32_t format, int plane); -extern const char *drm_get_format_name(uint32_t format); extern struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, unsigned int supported_rotations); extern unsigned int drm_rotation_simplify(unsigned int rotation, diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h new file mode 100644 index 000000000000..7f90a396cf2b --- /dev/null +++ b/include/drm/drm_fourcc.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 Laurent Pinchart laurent.pinchart@ideasonboard.com + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#ifndef __DRM_FOURCC_H__ +#define __DRM_FOURCC_H__ + +#include <linux/types.h> +#include <uapi/drm/drm_fourcc.h> + +void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp); +int drm_format_num_planes(uint32_t format); +int drm_format_plane_cpp(uint32_t format, int plane); +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); +const char *drm_get_format_name(uint32_t format); + +#endif /* __DRM_FOURCC_H__ */
Various pieces of information about DRM formats (number of planes, color depth, chroma subsampling, ...) are scattered across different helper functions in the DRM core. Callers of those functions often need to access more than a single parameter of the format, leading to inefficiencies due to multiple lookups.
Centralize all format information in a data structure and create a function to look up information based on the format 4CC.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/drm_fourcc.c | 84 ++++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_fourcc.h | 19 ++++++++++ 2 files changed, 103 insertions(+)
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 0645c85d5f95..47b9abd743be 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -62,6 +62,90 @@ const char *drm_get_format_name(uint32_t format) EXPORT_SYMBOL(drm_get_format_name);
/** + * drm_format_info - query information for a given format + * @format: pixel format (DRM_FORMAT_*) + * + * Returns: + * The instance of struct drm_format_info that describes the pixel format, or + * NULL if the format is unsupported. + */ +const struct drm_format_info *drm_format_info(u32 format) +{ + static const struct drm_format_info formats[] = { + { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGB332, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGR233, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XRGB4444, .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XBGR4444, .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBX4444, .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRX4444, .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ARGB4444, .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ABGR4444, .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBA4444, .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRA4444, .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ARGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ABGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGR888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_RGBA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 }, + { .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 }, + { .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 }, + { .format = DRM_FORMAT_YVU411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 }, + { .format = DRM_FORMAT_YUV420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 }, + { .format = DRM_FORMAT_YVU420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 }, + { .format = DRM_FORMAT_YUV422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_YVU422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_YUV444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_YVU444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_NV12, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 }, + { .format = DRM_FORMAT_NV21, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 }, + { .format = DRM_FORMAT_NV16, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_NV61, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_NV24, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_NV42, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 }, + { .format = DRM_FORMAT_YUYV, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 }, + { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, + }; + + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + if (formats[i].format == format) + return &formats[i]; + } + + return NULL; +} +EXPORT_SYMBOL(drm_format_info); + +/** * drm_fb_get_bpp_depth - get the bpp/depth values for format * @format: pixel format (DRM_FORMAT_*) * @depth: storage for the depth value diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index 7f90a396cf2b..b077df507b51 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -25,6 +25,25 @@ #include <linux/types.h> #include <uapi/drm/drm_fourcc.h>
+/** + * struct drm_format_info - information about a DRM format + * @format: 4CC format identifier (DRM_FORMAT_*) + * @depth: color depth (number of bits per pixel excluding padding bits) + * @num_planes: number of color planes (1 to 3) + * @cpp: number of bytes per pixel (per plane) + * @hsub: horizontal chroma subsampling factor + * @vsub: vertical chroma subsampling factor + */ +struct drm_format_info { + u32 format; + u8 depth; + u8 num_planes; + u8 cpp[3]; + u8 hsub; + u8 vsub; +}; + +const struct drm_format_info *drm_format_info(u32 format); void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp); int drm_format_num_planes(uint32_t format); int drm_format_plane_cpp(uint32_t format, int plane);
Turn the drm_format_*() helpers into wrappers around the drm_format_info lookup function to centralize all format information in a single place.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/drm_fourcc.c | 180 ++++++++----------------------------------- 1 file changed, 34 insertions(+), 146 deletions(-)
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 47b9abd743be..ef59e7f8032e 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -157,66 +157,19 @@ EXPORT_SYMBOL(drm_format_info); void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp) { - switch (format) { - case DRM_FORMAT_C8: - case DRM_FORMAT_RGB332: - case DRM_FORMAT_BGR233: - *depth = 8; - *bpp = 8; - break; - case DRM_FORMAT_XRGB1555: - case DRM_FORMAT_XBGR1555: - case DRM_FORMAT_RGBX5551: - case DRM_FORMAT_BGRX5551: - case DRM_FORMAT_ARGB1555: - case DRM_FORMAT_ABGR1555: - case DRM_FORMAT_RGBA5551: - case DRM_FORMAT_BGRA5551: - *depth = 15; - *bpp = 16; - break; - case DRM_FORMAT_RGB565: - case DRM_FORMAT_BGR565: - *depth = 16; - *bpp = 16; - break; - case DRM_FORMAT_RGB888: - case DRM_FORMAT_BGR888: - *depth = 24; - *bpp = 24; - break; - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_RGBX8888: - case DRM_FORMAT_BGRX8888: - *depth = 24; - *bpp = 32; - break; - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_RGBX1010102: - case DRM_FORMAT_BGRX1010102: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_RGBA1010102: - case DRM_FORMAT_BGRA1010102: - *depth = 30; - *bpp = 32; - break; - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_RGBA8888: - case DRM_FORMAT_BGRA8888: - *depth = 32; - *bpp = 32; - break; - default: + const struct drm_format_info *info; + + info = drm_format_info(format); + if (!info || !info->depth) { DRM_DEBUG_KMS("unsupported pixel format %s\n", drm_get_format_name(format)); *depth = 0; *bpp = 0; - break; + return; } + + *depth = info->depth; + *bpp = info->cpp[0] << 3; } EXPORT_SYMBOL(drm_fb_get_bpp_depth);
@@ -229,28 +182,10 @@ EXPORT_SYMBOL(drm_fb_get_bpp_depth); */ int drm_format_num_planes(uint32_t format) { - switch (format) { - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV444: - case DRM_FORMAT_YVU444: - return 3; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_NV24: - case DRM_FORMAT_NV42: - return 2; - default: - return 1; - } + const struct drm_format_info *info; + + info = drm_format_info(format); + return info ? info->num_planes : 1; } EXPORT_SYMBOL(drm_format_num_planes);
@@ -264,40 +199,13 @@ EXPORT_SYMBOL(drm_format_num_planes); */ int drm_format_plane_cpp(uint32_t format, int plane) { - unsigned int depth; - int bpp; + const struct drm_format_info *info;
- if (plane >= drm_format_num_planes(format)) + info = drm_format_info(format); + if (!info || plane >= info->num_planes) return 0;
- switch (format) { - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - return 2; - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_NV24: - case DRM_FORMAT_NV42: - return plane ? 2 : 1; - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV444: - case DRM_FORMAT_YVU444: - return 1; - default: - drm_fb_get_bpp_depth(format, &depth, &bpp); - return bpp >> 3; - } + return info->cpp[plane]; } EXPORT_SYMBOL(drm_format_plane_cpp);
@@ -311,28 +219,10 @@ EXPORT_SYMBOL(drm_format_plane_cpp); */ int drm_format_horz_chroma_subsampling(uint32_t format) { - switch (format) { - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - return 4; - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - return 2; - default: - return 1; - } + const struct drm_format_info *info; + + info = drm_format_info(format); + return info ? info->hsub : 1; } EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
@@ -346,18 +236,10 @@ EXPORT_SYMBOL(drm_format_horz_chroma_subsampling); */ int drm_format_vert_chroma_subsampling(uint32_t format) { - switch (format) { - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - return 4; - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - return 2; - default: - return 1; - } + const struct drm_format_info *info; + + info = drm_format_info(format); + return info ? info->vsub : 1; } EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
@@ -372,13 +254,16 @@ EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); */ int drm_format_plane_width(int width, uint32_t format, int plane) { - if (plane >= drm_format_num_planes(format)) + const struct drm_format_info *info; + + info = drm_format_info(format); + if (!info || plane >= info->num_planes) return 0;
if (plane == 0) return width;
- return width / drm_format_horz_chroma_subsampling(format); + return width / info->hsub; } EXPORT_SYMBOL(drm_format_plane_width);
@@ -393,12 +278,15 @@ EXPORT_SYMBOL(drm_format_plane_width); */ int drm_format_plane_height(int height, uint32_t format, int plane) { - if (plane >= drm_format_num_planes(format)) + const struct drm_format_info *info; + + info = drm_format_info(format); + if (!info || plane >= info->num_planes) return 0;
if (plane == 0) return height;
- return height / drm_format_vert_chroma_subsampling(format); + return height / info->vsub; } EXPORT_SYMBOL(drm_format_plane_height);
Replace calls to the drm_format_*() helper functions with direct use of the drm_format_info structure. This improves efficiency by removing duplicate lookups.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/drm_crtc.c | 100 +++++------------------------------- drivers/gpu/drm/drm_fb_cma_helper.c | 23 +++++---- 2 files changed, 25 insertions(+), 98 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index e5369529af06..73fa7f2a1a04 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3173,108 +3173,32 @@ int drm_mode_addfb(struct drm_device *dev, return 0; }
-static int format_check(const struct drm_mode_fb_cmd2 *r) -{ - uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN; - - switch (format) { - case DRM_FORMAT_C8: - case DRM_FORMAT_RGB332: - case DRM_FORMAT_BGR233: - case DRM_FORMAT_XRGB4444: - case DRM_FORMAT_XBGR4444: - case DRM_FORMAT_RGBX4444: - case DRM_FORMAT_BGRX4444: - case DRM_FORMAT_ARGB4444: - case DRM_FORMAT_ABGR4444: - case DRM_FORMAT_RGBA4444: - case DRM_FORMAT_BGRA4444: - case DRM_FORMAT_XRGB1555: - case DRM_FORMAT_XBGR1555: - case DRM_FORMAT_RGBX5551: - case DRM_FORMAT_BGRX5551: - case DRM_FORMAT_ARGB1555: - case DRM_FORMAT_ABGR1555: - case DRM_FORMAT_RGBA5551: - case DRM_FORMAT_BGRA5551: - case DRM_FORMAT_RGB565: - case DRM_FORMAT_BGR565: - case DRM_FORMAT_RGB888: - case DRM_FORMAT_BGR888: - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_RGBX8888: - case DRM_FORMAT_BGRX8888: - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_RGBA8888: - case DRM_FORMAT_BGRA8888: - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_RGBX1010102: - case DRM_FORMAT_BGRX1010102: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_RGBA1010102: - case DRM_FORMAT_BGRA1010102: - case DRM_FORMAT_YUYV: - case DRM_FORMAT_YVYU: - case DRM_FORMAT_UYVY: - case DRM_FORMAT_VYUY: - case DRM_FORMAT_AYUV: - case DRM_FORMAT_NV12: - case DRM_FORMAT_NV21: - case DRM_FORMAT_NV16: - case DRM_FORMAT_NV61: - case DRM_FORMAT_NV24: - case DRM_FORMAT_NV42: - case DRM_FORMAT_YUV410: - case DRM_FORMAT_YVU410: - case DRM_FORMAT_YUV411: - case DRM_FORMAT_YVU411: - case DRM_FORMAT_YUV420: - case DRM_FORMAT_YVU420: - case DRM_FORMAT_YUV422: - case DRM_FORMAT_YVU422: - case DRM_FORMAT_YUV444: - case DRM_FORMAT_YVU444: - return 0; - default: - DRM_DEBUG_KMS("invalid pixel format %s\n", - drm_get_format_name(r->pixel_format)); - return -EINVAL; - } -} - static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) { - int ret, hsub, vsub, num_planes, i; + const struct drm_format_info *info; + int i;
- ret = format_check(r); - if (ret) { + info = drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN); + if (!info) { DRM_DEBUG_KMS("bad framebuffer format %s\n", drm_get_format_name(r->pixel_format)); - return ret; + return -EINVAL; }
- hsub = drm_format_horz_chroma_subsampling(r->pixel_format); - vsub = drm_format_vert_chroma_subsampling(r->pixel_format); - num_planes = drm_format_num_planes(r->pixel_format); - - if (r->width == 0 || r->width % hsub) { + if (r->width == 0 || r->width % info->hsub) { DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); return -EINVAL; }
- if (r->height == 0 || r->height % vsub) { + if (r->height == 0 || r->height % info->vsub) { DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); return -EINVAL; }
- for (i = 0; i < num_planes; i++) { - unsigned int width = r->width / (i != 0 ? hsub : 1); - unsigned int height = r->height / (i != 0 ? vsub : 1); - unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i); + for (i = 0; i < info->num_planes; i++) { + unsigned int width = r->width / (i != 0 ? info->hsub : 1); + unsigned int height = r->height / (i != 0 ? info->vsub : 1); + unsigned int cpp = info->cpp[i];
if (!r->handles[i]) { DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i); @@ -3317,7 +3241,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) } }
- for (i = num_planes; i < 4; i++) { + for (i = info->num_planes; i < 4; i++) { if (r->modifier[i]) { DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i); return -EINVAL; diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c index 5075fae3c4e2..47e6d2616d39 100644 --- a/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/drivers/gpu/drm/drm_fb_cma_helper.c @@ -171,20 +171,20 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd, const struct drm_framebuffer_funcs *funcs) { + const struct drm_format_info *info; struct drm_fb_cma *fb_cma; struct drm_gem_cma_object *objs[4]; struct drm_gem_object *obj; - unsigned int hsub; - unsigned int vsub; int ret; int i;
- hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format); - vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format); + info = drm_format_info(mode_cmd->pixel_format); + if (!info) + return ERR_PTR(-EINVAL);
- for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) { - unsigned int width = mode_cmd->width / (i ? hsub : 1); - unsigned int height = mode_cmd->height / (i ? vsub : 1); + for (i = 0; i < info->num_planes; i++) { + unsigned int width = mode_cmd->width / (i ? info->hsub : 1); + unsigned int height = mode_cmd->height / (i ? info->vsub : 1); unsigned int min_size;
obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]); @@ -195,7 +195,7 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev, }
min_size = (height - 1) * mode_cmd->pitches[i] - + width * drm_format_plane_cpp(mode_cmd->pixel_format, i) + + width * info->cpp[i] + mode_cmd->offsets[i];
if (obj->size < min_size) { @@ -265,12 +265,15 @@ EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj); static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m) { struct drm_fb_cma *fb_cma = to_fb_cma(fb); - int i, n = drm_format_num_planes(fb->pixel_format); + const struct drm_format_info *info; + int i;
seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height, (char *)&fb->pixel_format);
- for (i = 0; i < n; i++) { + info = drm_format_info(fb->pixel_format); + + for (i = 0; i < info->num_planes; i++) { seq_printf(m, " %d: offset=%d pitch=%d, obj: ", i, fb->offsets[i], fb->pitches[i]); drm_gem_cma_describe(fb_cma->obj[i], m);
The format helpers have historically treated unsupported formats as part of the default case, returning values that are likely wrong. We can't change this behaviour now without risking breaking drivers in difficult to detect ways, but we can WARN on unsupported formats to catch faulty callers.
The only exception is the framebuffer_check() function that calls drm_format_info() to validate the format passed from userspace. This is a valid use case that shouldn't generate a warning.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/drm_crtc.c | 2 +- drivers/gpu/drm/drm_fourcc.c | 32 ++++++++++++++++++++++++-------- include/drm/drm_fourcc.h | 1 + 3 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 73fa7f2a1a04..1777ab37890a 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -3178,7 +3178,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) const struct drm_format_info *info; int i;
- info = drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN); + info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN); if (!info) { DRM_DEBUG_KMS("bad framebuffer format %s\n", drm_get_format_name(r->pixel_format)); diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index ef59e7f8032e..cb316e511ba9 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -61,15 +61,11 @@ const char *drm_get_format_name(uint32_t format) } EXPORT_SYMBOL(drm_get_format_name);
-/** - * drm_format_info - query information for a given format - * @format: pixel format (DRM_FORMAT_*) - * - * Returns: - * The instance of struct drm_format_info that describes the pixel format, or - * NULL if the format is unsupported. +/* + * Internal function to query information for a given format. See + * drm_format_info() for the public API. */ -const struct drm_format_info *drm_format_info(u32 format) +const struct drm_format_info *__drm_format_info(u32 format) { static const struct drm_format_info formats[] = { { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, @@ -143,6 +139,26 @@ const struct drm_format_info *drm_format_info(u32 format)
return NULL; } + +/** + * drm_format_info - query information for a given format + * @format: pixel format (DRM_FORMAT_*) + * + * The caller should only pass a supported pixel format to this function. + * Unsupported pixel formats will generate a warning in the kernel log. + * + * Returns: + * The instance of struct drm_format_info that describes the pixel format, or + * NULL if the format is unsupported. + */ +const struct drm_format_info *drm_format_info(u32 format) +{ + const struct drm_format_info *info; + + info = __drm_format_info(format); + WARN_ON(!info); + return info; +} EXPORT_SYMBOL(drm_format_info);
/** diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index b077df507b51..c9aa4e459358 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -43,6 +43,7 @@ struct drm_format_info { u8 vsub; };
+const struct drm_format_info *__drm_format_info(u32 format); const struct drm_format_info *drm_format_info(u32 format); void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp); int drm_format_num_planes(uint32_t format);
The driver needs the number of bytes per pixel, not the bpp and depth info meant for fbdev compatibility. Use the right API.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
Cc: Rob Clark robdclark@gmail.com Cc: linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 88fe256c1931..aa097b2376e7 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -496,8 +496,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, struct mdp5_kms *mdp5_kms = get_kms(crtc); struct drm_gem_object *cursor_bo, *old_bo = NULL; uint32_t blendcfg, cursor_addr, stride; - int ret, bpp, lm; - unsigned int depth; + int ret, lm; enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL; uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0); uint32_t roi_w, roi_h; @@ -527,8 +526,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, return -EINVAL;
lm = mdp5_crtc->lm; - drm_fb_get_bpp_depth(DRM_FORMAT_ARGB8888, &depth, &bpp); - stride = width * (bpp >> 3); + stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0);
spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags); old_bo = mdp5_crtc->cursor.scanout_bo;
The driver needs the number of bytes per pixel, not the bpp and depth info meant for fbdev compatibility. Use the right API.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/sti/sti_gdp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
Cc: Benjamin Gaignard benjamin.gaignard@linaro.org Cc: Vincent Abriou vincent.abriou@st.com
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c index ff33c38da197..be7e80535083 100644 --- a/drivers/gpu/drm/sti/sti_gdp.c +++ b/drivers/gpu/drm/sti/sti_gdp.c @@ -733,7 +733,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, u32 dma_updated_top; u32 dma_updated_btm; int format; - unsigned int depth, bpp; + unsigned int bpp; u32 ydo, xdo, yds, xds;
if (!crtc || !fb) @@ -772,9 +772,9 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane, (unsigned long)cma_obj->paddr);
/* pixel memory location */ - drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp); + bpp = drm_format_plane_cpp(fb->pixel_format, 0); top_field->gam_gdp_pml = (u32)cma_obj->paddr + fb->offsets[0]; - top_field->gam_gdp_pml += src_x * (bpp >> 3); + top_field->gam_gdp_pml += src_x * bpp; top_field->gam_gdp_pml += src_y * fb->pitches[0];
/* output parameters (clamped / cropped) */
The driver needs the number of bytes per pixel, not the bpp and depth info meant for fbdev compatibility. Use the right API.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/arm/hdlcd_crtc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
Cc: Liviu Dudau liviu.dudau@arm.com
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 0813c2f06931..b93a4ce01c50 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -242,14 +242,12 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, { struct hdlcd_drm_private *hdlcd; struct drm_gem_cma_object *gem; - unsigned int depth, bpp; u32 src_w, src_h, dest_w, dest_h; dma_addr_t scanout_start;
if (!plane->state->fb) return;
- drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp); src_w = plane->state->src_w >> 16; src_h = plane->state->src_h >> 16; dest_w = plane->state->crtc_w; @@ -257,7 +255,8 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane, gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0); scanout_start = gem->paddr + plane->state->fb->offsets[0] + plane->state->crtc_y * plane->state->fb->pitches[0] + - plane->state->crtc_x * bpp / 8; + plane->state->crtc_x * + drm_format_plane_cpp(plane->state->fb->pixel_format, 0);
hdlcd = plane->dev->dev_private; hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]);
The driver needs the number of bytes per pixel, not the bpp and depth info meant for fbdev compatibility. Use the right API.
In the tilcdc_crtc_mode_set() function compute the hardware register value directly from the pixel format instead of computing the number of bits per pixels first.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-)
Cc: Jyri Sarha jsarha@ti.com
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 79027b1c64d3..d63c7363dabc 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -65,15 +65,13 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb) struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_gem_cma_object *gem; - unsigned int depth, bpp; dma_addr_t start, end;
- drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp); gem = drm_fb_cma_get_gem_obj(fb, 0);
start = gem->paddr + fb->offsets[0] + crtc->y * fb->pitches[0] + - crtc->x * bpp / 8; + crtc->x * drm_format_plane_cpp(fb->pixel_format, 0);
end = start + (crtc->mode.vdisplay * fb->pitches[0]);
@@ -132,11 +130,12 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc) static int tilcdc_verify_fb(struct drm_crtc *crtc, struct drm_framebuffer *fb) { struct drm_device *dev = crtc->dev; - unsigned int depth, bpp; + unsigned int min_pitch;
- drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp); + min_pitch = crtc->mode.hdisplay + * drm_format_plane_cpp(fb->pixel_format, 0);
- if (fb->pitches[0] != crtc->mode.hdisplay * bpp / 8) { + if (fb->pitches[0] != min_pitch) { dev_err(dev->dev, "Invalid pitch: fb and crtc widths must be the same"); return -EINVAL; @@ -401,16 +400,14 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, if (info->tft_alt_mode) reg |= LCDC_TFT_ALT_ENABLE; if (priv->rev == 2) { - unsigned int depth, bpp; - - drm_fb_get_bpp_depth(crtc->primary->fb->pixel_format, &depth, &bpp); - switch (bpp) { - case 16: + switch (crtc->primary->fb->pixel_format) { + case DRM_FORMAT_RGB565: break; - case 32: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: reg |= LCDC_V2_TFT_24BPP_UNPACK; /* fallthrough */ - case 24: + case DRM_FORMAT_RGB888: reg |= LCDC_V2_TFT_24BPP_MODE; break; default:
The driver doesn't need the color depth, only the number of bits per pixel. Use the right API.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/cirrus/cirrus_fbdev.c | 6 +++--- drivers/gpu/drm/cirrus/cirrus_main.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-)
Cc: Dave Airlie airlied@redhat.com
diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c index 3b5be7272357..3d0e900c8f95 100644 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c @@ -140,12 +140,12 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev, { struct drm_device *dev = afbdev->helper.dev; struct cirrus_device *cdev = dev->dev_private; - u32 bpp, depth; + u32 bpp; u32 size; struct drm_gem_object *gobj; - int ret = 0; - drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + + bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8;
if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height, bpp, mode_cmd->pitches[0])) diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c index 32d32c5b7b17..4c9df1fbdece 100644 --- a/drivers/gpu/drm/cirrus/cirrus_main.c +++ b/drivers/gpu/drm/cirrus/cirrus_main.c @@ -52,10 +52,10 @@ cirrus_user_framebuffer_create(struct drm_device *dev, struct cirrus_device *cdev = dev->dev_private; struct drm_gem_object *obj; struct cirrus_framebuffer *cirrus_fb; + u32 bpp; int ret; - u32 bpp, depth;
- drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8;
if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height, bpp, mode_cmd->pitches[0]))
The driver uses drm_fb_get_bpp_depth() to check whether it can support the format requested by userspace when creating a framebuffer. This isn't the right API, as it doesn't differentiate between RGB formats other than on a depth and bpp basis.
Fixing this requires non trivial changes to the drivers internals. As a first step, replace usage of the drm_fb_get_bpp_depth() function with an equivalent check based on drm_format_info(). This is part of a wider effort to remove usage of the drm_fb_get_bpp_depth() function in drivers.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/gma500/framebuffer.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-)
Cc: Patrik Jakobsson patrik.r.jakobsson@gmail.com
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 7440bf90ac9c..659707a5e85d 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -246,22 +246,20 @@ static int psb_framebuffer_init(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd, struct gtt_range *gt) { - u32 bpp, depth; + const struct drm_format_info *info; int ret;
- drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + /* + * Reject unknown formats, YUV formats, and formats with more than + * 4 bytes per pixel. + */ + info = drm_format_info(mode_cmd->pixel_format); + if (!info || !info->depth || info->cpp[0] > 4) + return -EINVAL;
if (mode_cmd->pitches[0] & 63) return -EINVAL; - switch (bpp) { - case 8: - case 16: - case 24: - case 32: - break; - default: - return -EINVAL; - } + drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); fb->gtt = gt; ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
The driver needs the number of bytes per pixel, not the bpp and depth info meant for fbdev compatibility. Use the right API.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 10 +++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-)
Cc: Alex Deucher alexander.deucher@amd.com Cc: "Christian König" christian.koenig@amd.com
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 919146780a15..306f626d3e80 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -68,7 +68,7 @@ int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tile int aligned = width; int pitch_mask = 0;
- switch (bpp / 8) { + switch (bpp) { case 1: pitch_mask = 255; break; @@ -83,7 +83,7 @@ int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tile
aligned += pitch_mask; aligned &= ~pitch_mask; - return aligned; + return aligned * bpp; }
static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj) @@ -112,13 +112,13 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, int ret; int aligned_size, size; int height = mode_cmd->height; - u32 bpp, depth; + u32 bpp;
- drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0);
/* need to align pitch with crtc limits */ mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, bpp, - fb_tiled) * ((bpp + 1) / 8); + fb_tiled);
height = ALIGN(mode_cmd->height, 8); size = mode_cmd->pitches[0] * height; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 8fab6486064f..232230f14769 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -704,7 +704,8 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, uint32_t handle; int r;
- args->pitch = amdgpu_align_pitch(adev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8); + args->pitch = amdgpu_align_pitch(adev, args->width, + DIV_ROUND_UP(args->bpp, 8), 0); args->size = (u64)args->pitch * args->height; args->size = ALIGN(args->size, PAGE_SIZE);
The driver needs the number of bytes per pixel, not the bpp and depth info meant for fbdev compatibility. Use the right API.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/radeon/radeon_fb.c | 14 +++++++------- drivers/gpu/drm/radeon/radeon_gem.c | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-)
Cc: Alex Deucher alexander.deucher@amd.com Cc: "Christian König" christian.koenig@amd.com
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 0e3143acb565..f5878ca7d730 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -68,7 +68,7 @@ int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tile int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; int pitch_mask = 0;
- switch (bpp / 8) { + switch (bpp) { case 1: pitch_mask = align_large ? 255 : 127; break; @@ -83,7 +83,7 @@ int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tile
aligned += pitch_mask; aligned &= ~pitch_mask; - return aligned; + return aligned * bpp; }
static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) @@ -112,13 +112,13 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, int ret; int aligned_size, size; int height = mode_cmd->height; - u32 bpp, depth; + u32 bpp;
- drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0);
/* need to align pitch with crtc limits */ mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, bpp, - fb_tiled) * ((bpp + 1) / 8); + fb_tiled);
if (rdev->family >= CHIP_R600) height = ALIGN(mode_cmd->height, 8); @@ -139,10 +139,10 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
#ifdef __BIG_ENDIAN switch (bpp) { - case 32: + case 4: tiling_flags |= RADEON_TILING_SWAP_32BIT; break; - case 16: + case 2: tiling_flags |= RADEON_TILING_SWAP_16BIT; default: break; diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index deb9511725c9..0bcffd8a7bd3 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -745,7 +745,8 @@ int radeon_mode_dumb_create(struct drm_file *file_priv, uint32_t handle; int r;
- args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8); + args->pitch = radeon_align_pitch(rdev, args->width, + DIV_ROUND_UP(args->bpp, 8), 0); args->size = args->pitch * args->height; args->size = ALIGN(args->size, PAGE_SIZE);
The driver is the last users of the drm_fb_get_bpp_depth() function. It should ideally be converted to use struct drm_mode_fb_cmd2 instead of the legacy struct drm_mode_fb_cmd internally, but that will require broad changes across the code base. As a first step, replace drm_fb_get_bpp_depth() with drm_format_info() in order to stop exporting the function to drivers.
The new DRM_ERROR() message comes from the vmw_create_dmabuf_proxy(), vmw_kms_new_framebuffer_surface() and vmw_kms_new_framebuffer_dmabuf() functions that currently print an error if the pixel format is unsupported.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
Cc: VMware Graphics linux-graphics-maintainer@vmware.com Cc: Sinclair Yeh syeh@vmware.com Cc: Thomas Hellstrom thellstrom@vmware.com
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 55231cce73a0..1a7187f472de 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -980,14 +980,22 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, struct vmw_dma_buffer *bo = NULL; struct ttm_base_object *user_obj; struct drm_mode_fb_cmd mode_cmd; + const struct drm_format_info *info; int ret;
+ info = drm_format_info(mode_cmd2->pixel_format); + if (!info || !info->depth) { + DRM_ERROR("Unsupported framebuffer format %s\n", + drm_get_format_name(mode_cmd2->pixel_format)); + return ERR_PTR(-EINVAL); + } + mode_cmd.width = mode_cmd2->width; mode_cmd.height = mode_cmd2->height; mode_cmd.pitch = mode_cmd2->pitches[0]; mode_cmd.handle = mode_cmd2->handles[0]; - drm_fb_get_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth, - &mode_cmd.bpp); + mode_cmd.depth = info->depth; + mode_cmd.bpp = info->cpp[0] * 8;
/** * This code should be conditioned on Screen Objects not being used.
The function is only used by the drm_helper_mode_fill_fb_struct() core function to fill the drm_framebuffer bpp and depth fields, used by drivers that haven't been converted to use pixel formats directly yet. It should not be used by new drivers, so inline it in its only caller.
Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/drm_crtc_helper.c | 14 ++++++++++++-- drivers/gpu/drm/drm_fourcc.c | 28 ---------------------------- include/drm/drm_fourcc.h | 1 - 3 files changed, 12 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index a6e42433ef0e..3619af2cbe96 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -918,8 +918,20 @@ EXPORT_SYMBOL(drm_helper_connector_dpms); void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, const struct drm_mode_fb_cmd2 *mode_cmd) { + const struct drm_format_info *info; int i;
+ info = drm_format_info(mode_cmd->pixel_format); + if (!info || !info->depth) { + DRM_DEBUG_KMS("non-RGB pixel format %s\n", + drm_get_format_name(mode_cmd->pixel_format)); + fb->depth = 0; + fb->bits_per_pixel = 0; + } else { + fb->depth = info->depth; + fb->bits_per_pixel = info->cpp[0] << 3; + } + fb->width = mode_cmd->width; fb->height = mode_cmd->height; for (i = 0; i < 4; i++) { @@ -927,8 +939,6 @@ void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, fb->offsets[i] = mode_cmd->offsets[i]; fb->modifier[i] = mode_cmd->modifier[i]; } - drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, - &fb->bits_per_pixel); fb->pixel_format = mode_cmd->pixel_format; fb->flags = mode_cmd->flags; } diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index cb316e511ba9..d8f3fdfe57eb 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -162,34 +162,6 @@ const struct drm_format_info *drm_format_info(u32 format) EXPORT_SYMBOL(drm_format_info);
/** - * drm_fb_get_bpp_depth - get the bpp/depth values for format - * @format: pixel format (DRM_FORMAT_*) - * @depth: storage for the depth value - * @bpp: storage for the bpp value - * - * This only supports RGB formats here for compat with code that doesn't use - * pixel formats directly yet. - */ -void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, - int *bpp) -{ - const struct drm_format_info *info; - - info = drm_format_info(format); - if (!info || !info->depth) { - DRM_DEBUG_KMS("unsupported pixel format %s\n", - drm_get_format_name(format)); - *depth = 0; - *bpp = 0; - return; - } - - *depth = info->depth; - *bpp = info->cpp[0] << 3; -} -EXPORT_SYMBOL(drm_fb_get_bpp_depth); - -/** * drm_format_num_planes - get the number of planes for format * @format: pixel format (DRM_FORMAT_*) * diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h index c9aa4e459358..1f4746bc0eae 100644 --- a/include/drm/drm_fourcc.h +++ b/include/drm/drm_fourcc.h @@ -45,7 +45,6 @@ struct drm_format_info {
const struct drm_format_info *__drm_format_info(u32 format); const struct drm_format_info *drm_format_info(u32 format); -void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp); int drm_format_num_planes(uint32_t format); int drm_format_plane_cpp(uint32_t format, int plane); int drm_format_horz_chroma_subsampling(uint32_t format);
dri-devel@lists.freedesktop.org