diff options
Diffstat (limited to 'drivers/gpu/drm/drm_fourcc.c')
| -rw-r--r-- | drivers/gpu/drm/drm_fourcc.c | 335 | 
1 files changed, 166 insertions, 169 deletions
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 0645c85d5f95..90d2cc8da8eb 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -36,19 +36,56 @@ static char printable_char(int 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. + * drm_mode_legacy_fb_format - compute drm fourcc code from legacy description + * @bpp: bits per pixels + * @depth: bit depth per pixel   * - * FIXME: This isn't really multithreading safe. + * Computes a drm fourcc pixel format code for the given @bpp/@depth values. + * Useful in fbdev emulation code, since that deals in those values.   */ -const char *drm_get_format_name(uint32_t format) +uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)  { -	static char buf[32]; +	uint32_t fmt; -	snprintf(buf, sizeof(buf), +	switch (bpp) { +	case 8: +		fmt = DRM_FORMAT_C8; +		break; +	case 16: +		if (depth == 15) +			fmt = DRM_FORMAT_XRGB1555; +		else +			fmt = DRM_FORMAT_RGB565; +		break; +	case 24: +		fmt = DRM_FORMAT_RGB888; +		break; +	case 32: +		if (depth == 24) +			fmt = DRM_FORMAT_XRGB8888; +		else if (depth == 30) +			fmt = DRM_FORMAT_XRGB2101010; +		else +			fmt = DRM_FORMAT_ARGB8888; +		break; +	default: +		DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n"); +		fmt = DRM_FORMAT_XRGB8888; +		break; +	} + +	return fmt; +} +EXPORT_SYMBOL(drm_mode_legacy_fb_format); + +/** + * drm_get_format_name - fill a string with a drm fourcc format's name + * @format: format to compute name of + * @buf: caller-supplied buffer + */ +const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf) +{ +	snprintf(buf->str, sizeof(buf->str),  		 "%c%c%c%c %s-endian (0x%08x)",  		 printable_char(format & 0xff),  		 printable_char((format >> 8) & 0xff), @@ -57,84 +94,109 @@ const char *drm_get_format_name(uint32_t format)  		 format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",  		 format); -	return buf; +	return buf->str;  }  EXPORT_SYMBOL(drm_get_format_name); +/* + * 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) +{ +	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 = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, +		{ .format = DRM_FORMAT_XBGR4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, +		{ .format = DRM_FORMAT_RGBX4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, +		{ .format = DRM_FORMAT_BGRX4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, +		{ .format = DRM_FORMAT_ARGB4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, +		{ .format = DRM_FORMAT_ABGR4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, +		{ .format = DRM_FORMAT_RGBA4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, +		{ .format = DRM_FORMAT_BGRA4444,	.depth = 0,  .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; +} +  /** - * drm_fb_get_bpp_depth - get the bpp/depth values for format + * drm_format_info - query information for a given 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. + * 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.   */ -void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, -			  int *bpp) +const struct drm_format_info *drm_format_info(u32 format)  { -	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; -	} +	const struct drm_format_info *info; + +	info = __drm_format_info(format); +	WARN_ON(!info); +	return info;  } -EXPORT_SYMBOL(drm_fb_get_bpp_depth); +EXPORT_SYMBOL(drm_format_info);  /**   * drm_format_num_planes - get the number of planes for format @@ -145,28 +207,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); @@ -180,40 +224,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); @@ -227,28 +244,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); @@ -262,18 +261,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); @@ -288,13 +279,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); @@ -309,12 +303,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);  | 
