drm_fourcc.c revision 1.2 1 1.1 riastrad /* $NetBSD: drm_fourcc.c,v 1.2 2021/12/18 23:44:57 riastradh Exp $ */
2 1.1 riastrad
3 1.1 riastrad /*
4 1.1 riastrad * Copyright (c) 2016 Laurent Pinchart <laurent.pinchart (at) ideasonboard.com>
5 1.1 riastrad *
6 1.1 riastrad * DRM core format related functions
7 1.1 riastrad *
8 1.1 riastrad * Permission to use, copy, modify, distribute, and sell this software and its
9 1.1 riastrad * documentation for any purpose is hereby granted without fee, provided that
10 1.1 riastrad * the above copyright notice appear in all copies and that both that copyright
11 1.1 riastrad * notice and this permission notice appear in supporting documentation, and
12 1.1 riastrad * that the name of the copyright holders not be used in advertising or
13 1.1 riastrad * publicity pertaining to distribution of the software without specific,
14 1.1 riastrad * written prior permission. The copyright holders make no representations
15 1.1 riastrad * about the suitability of this software for any purpose. It is provided "as
16 1.1 riastrad * is" without express or implied warranty.
17 1.1 riastrad *
18 1.1 riastrad * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 1.1 riastrad * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
20 1.1 riastrad * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21 1.1 riastrad * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22 1.1 riastrad * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
23 1.1 riastrad * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 1.1 riastrad * OF THIS SOFTWARE.
25 1.1 riastrad */
26 1.1 riastrad
27 1.1 riastrad #include <sys/cdefs.h>
28 1.1 riastrad __KERNEL_RCSID(0, "$NetBSD: drm_fourcc.c,v 1.2 2021/12/18 23:44:57 riastradh Exp $");
29 1.1 riastrad
30 1.1 riastrad #include <linux/bug.h>
31 1.1 riastrad #include <linux/ctype.h>
32 1.1 riastrad #include <linux/export.h>
33 1.1 riastrad #include <linux/kernel.h>
34 1.1 riastrad
35 1.1 riastrad #include <drm/drm_device.h>
36 1.1 riastrad #include <drm/drm_fourcc.h>
37 1.1 riastrad
38 1.1 riastrad static char printable_char(int c)
39 1.1 riastrad {
40 1.1 riastrad return isascii(c) && isprint(c) ? c : '?';
41 1.1 riastrad }
42 1.1 riastrad
43 1.1 riastrad /**
44 1.1 riastrad * drm_mode_legacy_fb_format - compute drm fourcc code from legacy description
45 1.1 riastrad * @bpp: bits per pixels
46 1.1 riastrad * @depth: bit depth per pixel
47 1.1 riastrad *
48 1.1 riastrad * Computes a drm fourcc pixel format code for the given @bpp/@depth values.
49 1.1 riastrad * Useful in fbdev emulation code, since that deals in those values.
50 1.1 riastrad */
51 1.1 riastrad uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
52 1.1 riastrad {
53 1.1 riastrad uint32_t fmt = DRM_FORMAT_INVALID;
54 1.1 riastrad
55 1.1 riastrad switch (bpp) {
56 1.1 riastrad case 8:
57 1.1 riastrad if (depth == 8)
58 1.1 riastrad fmt = DRM_FORMAT_C8;
59 1.1 riastrad break;
60 1.1 riastrad
61 1.1 riastrad case 16:
62 1.1 riastrad switch (depth) {
63 1.1 riastrad case 15:
64 1.1 riastrad fmt = DRM_FORMAT_XRGB1555;
65 1.1 riastrad break;
66 1.1 riastrad case 16:
67 1.1 riastrad fmt = DRM_FORMAT_RGB565;
68 1.1 riastrad break;
69 1.1 riastrad default:
70 1.1 riastrad break;
71 1.1 riastrad }
72 1.1 riastrad break;
73 1.1 riastrad
74 1.1 riastrad case 24:
75 1.1 riastrad if (depth == 24)
76 1.1 riastrad fmt = DRM_FORMAT_RGB888;
77 1.1 riastrad break;
78 1.1 riastrad
79 1.1 riastrad case 32:
80 1.1 riastrad switch (depth) {
81 1.1 riastrad case 24:
82 1.1 riastrad fmt = DRM_FORMAT_XRGB8888;
83 1.1 riastrad break;
84 1.1 riastrad case 30:
85 1.1 riastrad fmt = DRM_FORMAT_XRGB2101010;
86 1.1 riastrad break;
87 1.1 riastrad case 32:
88 1.1 riastrad fmt = DRM_FORMAT_ARGB8888;
89 1.1 riastrad break;
90 1.1 riastrad default:
91 1.1 riastrad break;
92 1.1 riastrad }
93 1.1 riastrad break;
94 1.1 riastrad
95 1.1 riastrad default:
96 1.1 riastrad break;
97 1.1 riastrad }
98 1.1 riastrad
99 1.1 riastrad return fmt;
100 1.1 riastrad }
101 1.1 riastrad EXPORT_SYMBOL(drm_mode_legacy_fb_format);
102 1.1 riastrad
103 1.1 riastrad /**
104 1.1 riastrad * drm_driver_legacy_fb_format - compute drm fourcc code from legacy description
105 1.1 riastrad * @dev: DRM device
106 1.1 riastrad * @bpp: bits per pixels
107 1.1 riastrad * @depth: bit depth per pixel
108 1.1 riastrad *
109 1.1 riastrad * Computes a drm fourcc pixel format code for the given @bpp/@depth values.
110 1.1 riastrad * Unlike drm_mode_legacy_fb_format() this looks at the drivers mode_config,
111 1.1 riastrad * and depending on the &drm_mode_config.quirk_addfb_prefer_host_byte_order flag
112 1.1 riastrad * it returns little endian byte order or host byte order framebuffer formats.
113 1.1 riastrad */
114 1.1 riastrad uint32_t drm_driver_legacy_fb_format(struct drm_device *dev,
115 1.1 riastrad uint32_t bpp, uint32_t depth)
116 1.1 riastrad {
117 1.1 riastrad uint32_t fmt = drm_mode_legacy_fb_format(bpp, depth);
118 1.1 riastrad
119 1.1 riastrad if (dev->mode_config.quirk_addfb_prefer_host_byte_order) {
120 1.1 riastrad if (fmt == DRM_FORMAT_XRGB8888)
121 1.1 riastrad fmt = DRM_FORMAT_HOST_XRGB8888;
122 1.1 riastrad if (fmt == DRM_FORMAT_ARGB8888)
123 1.1 riastrad fmt = DRM_FORMAT_HOST_ARGB8888;
124 1.1 riastrad if (fmt == DRM_FORMAT_RGB565)
125 1.1 riastrad fmt = DRM_FORMAT_HOST_RGB565;
126 1.1 riastrad if (fmt == DRM_FORMAT_XRGB1555)
127 1.1 riastrad fmt = DRM_FORMAT_HOST_XRGB1555;
128 1.1 riastrad }
129 1.1 riastrad
130 1.1 riastrad if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp &&
131 1.1 riastrad fmt == DRM_FORMAT_XRGB2101010)
132 1.1 riastrad fmt = DRM_FORMAT_XBGR2101010;
133 1.1 riastrad
134 1.1 riastrad return fmt;
135 1.1 riastrad }
136 1.1 riastrad EXPORT_SYMBOL(drm_driver_legacy_fb_format);
137 1.1 riastrad
138 1.1 riastrad /**
139 1.1 riastrad * drm_get_format_name - fill a string with a drm fourcc format's name
140 1.1 riastrad * @format: format to compute name of
141 1.1 riastrad * @buf: caller-supplied buffer
142 1.1 riastrad */
143 1.1 riastrad const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf)
144 1.1 riastrad {
145 1.1 riastrad snprintf(buf->str, sizeof(buf->str),
146 1.1 riastrad "%c%c%c%c %s-endian (0x%08x)",
147 1.1 riastrad printable_char(format & 0xff),
148 1.1 riastrad printable_char((format >> 8) & 0xff),
149 1.1 riastrad printable_char((format >> 16) & 0xff),
150 1.1 riastrad printable_char((format >> 24) & 0x7f),
151 1.1 riastrad format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
152 1.1 riastrad format);
153 1.1 riastrad
154 1.1 riastrad return buf->str;
155 1.1 riastrad }
156 1.1 riastrad EXPORT_SYMBOL(drm_get_format_name);
157 1.1 riastrad
158 1.1 riastrad /*
159 1.1 riastrad * Internal function to query information for a given format. See
160 1.1 riastrad * drm_format_info() for the public API.
161 1.1 riastrad */
162 1.1 riastrad const struct drm_format_info *__drm_format_info(u32 format)
163 1.1 riastrad {
164 1.1 riastrad static const struct drm_format_info formats[] = {
165 1.1 riastrad { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
166 1.1 riastrad { .format = DRM_FORMAT_RGB332, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
167 1.1 riastrad { .format = DRM_FORMAT_BGR233, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
168 1.1 riastrad { .format = DRM_FORMAT_XRGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
169 1.1 riastrad { .format = DRM_FORMAT_XBGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
170 1.1 riastrad { .format = DRM_FORMAT_RGBX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
171 1.1 riastrad { .format = DRM_FORMAT_BGRX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
172 1.1 riastrad { .format = DRM_FORMAT_ARGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
173 1.1 riastrad { .format = DRM_FORMAT_ABGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
174 1.1 riastrad { .format = DRM_FORMAT_RGBA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
175 1.1 riastrad { .format = DRM_FORMAT_BGRA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
176 1.1 riastrad { .format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
177 1.1 riastrad { .format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
178 1.1 riastrad { .format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
179 1.1 riastrad { .format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
180 1.1 riastrad { .format = DRM_FORMAT_ARGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
181 1.1 riastrad { .format = DRM_FORMAT_ABGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
182 1.1 riastrad { .format = DRM_FORMAT_RGBA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
183 1.1 riastrad { .format = DRM_FORMAT_BGRA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
184 1.1 riastrad { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
185 1.1 riastrad { .format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
186 1.1 riastrad { .format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
187 1.1 riastrad { .format = DRM_FORMAT_BGR888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
188 1.1 riastrad { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
189 1.1 riastrad { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
190 1.1 riastrad { .format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
191 1.1 riastrad { .format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
192 1.1 riastrad { .format = DRM_FORMAT_RGB565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
193 1.1 riastrad { .format = DRM_FORMAT_BGR565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
194 1.1 riastrad { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
195 1.1 riastrad { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
196 1.1 riastrad { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
197 1.1 riastrad { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
198 1.1 riastrad { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
199 1.1 riastrad { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
200 1.1 riastrad { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
201 1.1 riastrad { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
202 1.1 riastrad { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
203 1.1 riastrad { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
204 1.1 riastrad { .format = DRM_FORMAT_RGBA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
205 1.1 riastrad { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
206 1.1 riastrad { .format = DRM_FORMAT_XRGB16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 },
207 1.1 riastrad { .format = DRM_FORMAT_XBGR16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 },
208 1.1 riastrad { .format = DRM_FORMAT_ARGB16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
209 1.1 riastrad { .format = DRM_FORMAT_ABGR16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
210 1.1 riastrad { .format = DRM_FORMAT_RGB888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
211 1.1 riastrad { .format = DRM_FORMAT_BGR888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
212 1.1 riastrad { .format = DRM_FORMAT_XRGB8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
213 1.1 riastrad { .format = DRM_FORMAT_XBGR8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
214 1.1 riastrad { .format = DRM_FORMAT_RGBX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
215 1.1 riastrad { .format = DRM_FORMAT_BGRX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
216 1.1 riastrad { .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true },
217 1.1 riastrad { .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true },
218 1.1 riastrad { .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true },
219 1.1 riastrad { .format = DRM_FORMAT_YVU411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true },
220 1.1 riastrad { .format = DRM_FORMAT_YUV420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true },
221 1.1 riastrad { .format = DRM_FORMAT_YVU420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true },
222 1.1 riastrad { .format = DRM_FORMAT_YUV422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true },
223 1.1 riastrad { .format = DRM_FORMAT_YVU422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true },
224 1.1 riastrad { .format = DRM_FORMAT_YUV444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true },
225 1.1 riastrad { .format = DRM_FORMAT_YVU444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true },
226 1.1 riastrad { .format = DRM_FORMAT_NV12, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
227 1.1 riastrad { .format = DRM_FORMAT_NV21, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true },
228 1.1 riastrad { .format = DRM_FORMAT_NV16, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
229 1.1 riastrad { .format = DRM_FORMAT_NV61, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
230 1.1 riastrad { .format = DRM_FORMAT_NV24, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
231 1.1 riastrad { .format = DRM_FORMAT_NV42, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
232 1.1 riastrad { .format = DRM_FORMAT_YUYV, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
233 1.1 riastrad { .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
234 1.1 riastrad { .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
235 1.1 riastrad { .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
236 1.1 riastrad { .format = DRM_FORMAT_XYUV8888, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
237 1.1 riastrad { .format = DRM_FORMAT_VUY888, .depth = 0, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
238 1.1 riastrad { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
239 1.1 riastrad { .format = DRM_FORMAT_Y210, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
240 1.1 riastrad { .format = DRM_FORMAT_Y212, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
241 1.1 riastrad { .format = DRM_FORMAT_Y216, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
242 1.1 riastrad { .format = DRM_FORMAT_Y410, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
243 1.1 riastrad { .format = DRM_FORMAT_Y412, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
244 1.1 riastrad { .format = DRM_FORMAT_Y416, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true },
245 1.1 riastrad { .format = DRM_FORMAT_XVYU2101010, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
246 1.1 riastrad { .format = DRM_FORMAT_XVYU12_16161616, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
247 1.1 riastrad { .format = DRM_FORMAT_XVYU16161616, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
248 1.1 riastrad { .format = DRM_FORMAT_Y0L0, .depth = 0, .num_planes = 1,
249 1.1 riastrad .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 },
250 1.1 riastrad .hsub = 2, .vsub = 2, .has_alpha = true, .is_yuv = true },
251 1.1 riastrad { .format = DRM_FORMAT_X0L0, .depth = 0, .num_planes = 1,
252 1.1 riastrad .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 },
253 1.1 riastrad .hsub = 2, .vsub = 2, .is_yuv = true },
254 1.1 riastrad { .format = DRM_FORMAT_Y0L2, .depth = 0, .num_planes = 1,
255 1.1 riastrad .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 },
256 1.1 riastrad .hsub = 2, .vsub = 2, .has_alpha = true, .is_yuv = true },
257 1.1 riastrad { .format = DRM_FORMAT_X0L2, .depth = 0, .num_planes = 1,
258 1.1 riastrad .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 },
259 1.1 riastrad .hsub = 2, .vsub = 2, .is_yuv = true },
260 1.1 riastrad { .format = DRM_FORMAT_P010, .depth = 0, .num_planes = 2,
261 1.1 riastrad .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 },
262 1.1 riastrad .hsub = 2, .vsub = 2, .is_yuv = true},
263 1.1 riastrad { .format = DRM_FORMAT_P012, .depth = 0, .num_planes = 2,
264 1.1 riastrad .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 },
265 1.1 riastrad .hsub = 2, .vsub = 2, .is_yuv = true},
266 1.1 riastrad { .format = DRM_FORMAT_P016, .depth = 0, .num_planes = 2,
267 1.1 riastrad .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 },
268 1.1 riastrad .hsub = 2, .vsub = 2, .is_yuv = true},
269 1.1 riastrad { .format = DRM_FORMAT_P210, .depth = 0,
270 1.1 riastrad .num_planes = 2, .char_per_block = { 2, 4, 0 },
271 1.1 riastrad .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2,
272 1.1 riastrad .vsub = 1, .is_yuv = true },
273 1.1 riastrad { .format = DRM_FORMAT_VUY101010, .depth = 0,
274 1.1 riastrad .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 1, .vsub = 1,
275 1.1 riastrad .is_yuv = true },
276 1.1 riastrad { .format = DRM_FORMAT_YUV420_8BIT, .depth = 0,
277 1.1 riastrad .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2,
278 1.1 riastrad .is_yuv = true },
279 1.1 riastrad { .format = DRM_FORMAT_YUV420_10BIT, .depth = 0,
280 1.1 riastrad .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2,
281 1.1 riastrad .is_yuv = true },
282 1.1 riastrad };
283 1.1 riastrad
284 1.1 riastrad unsigned int i;
285 1.1 riastrad
286 1.1 riastrad for (i = 0; i < ARRAY_SIZE(formats); ++i) {
287 1.1 riastrad if (formats[i].format == format)
288 1.1 riastrad return &formats[i];
289 1.1 riastrad }
290 1.1 riastrad
291 1.1 riastrad return NULL;
292 1.1 riastrad }
293 1.1 riastrad
294 1.1 riastrad /**
295 1.1 riastrad * drm_format_info - query information for a given format
296 1.1 riastrad * @format: pixel format (DRM_FORMAT_*)
297 1.1 riastrad *
298 1.1 riastrad * The caller should only pass a supported pixel format to this function.
299 1.1 riastrad * Unsupported pixel formats will generate a warning in the kernel log.
300 1.1 riastrad *
301 1.1 riastrad * Returns:
302 1.1 riastrad * The instance of struct drm_format_info that describes the pixel format, or
303 1.1 riastrad * NULL if the format is unsupported.
304 1.1 riastrad */
305 1.1 riastrad const struct drm_format_info *drm_format_info(u32 format)
306 1.1 riastrad {
307 1.1 riastrad const struct drm_format_info *info;
308 1.1 riastrad
309 1.1 riastrad info = __drm_format_info(format);
310 1.1 riastrad WARN_ON(!info);
311 1.1 riastrad return info;
312 1.1 riastrad }
313 1.1 riastrad EXPORT_SYMBOL(drm_format_info);
314 1.1 riastrad
315 1.1 riastrad /**
316 1.1 riastrad * drm_get_format_info - query information for a given framebuffer configuration
317 1.1 riastrad * @dev: DRM device
318 1.1 riastrad * @mode_cmd: metadata from the userspace fb creation request
319 1.1 riastrad *
320 1.1 riastrad * Returns:
321 1.1 riastrad * The instance of struct drm_format_info that describes the pixel format, or
322 1.1 riastrad * NULL if the format is unsupported.
323 1.1 riastrad */
324 1.1 riastrad const struct drm_format_info *
325 1.1 riastrad drm_get_format_info(struct drm_device *dev,
326 1.1 riastrad const struct drm_mode_fb_cmd2 *mode_cmd)
327 1.1 riastrad {
328 1.1 riastrad const struct drm_format_info *info = NULL;
329 1.1 riastrad
330 1.1 riastrad if (dev->mode_config.funcs->get_format_info)
331 1.1 riastrad info = dev->mode_config.funcs->get_format_info(mode_cmd);
332 1.1 riastrad
333 1.1 riastrad if (!info)
334 1.1 riastrad info = drm_format_info(mode_cmd->pixel_format);
335 1.1 riastrad
336 1.1 riastrad return info;
337 1.1 riastrad }
338 1.1 riastrad EXPORT_SYMBOL(drm_get_format_info);
339 1.1 riastrad
340 1.1 riastrad /**
341 1.1 riastrad * drm_format_info_block_width - width in pixels of block.
342 1.1 riastrad * @info: pixel format info
343 1.1 riastrad * @plane: plane index
344 1.1 riastrad *
345 1.1 riastrad * Returns:
346 1.1 riastrad * The width in pixels of a block, depending on the plane index.
347 1.1 riastrad */
348 1.1 riastrad unsigned int drm_format_info_block_width(const struct drm_format_info *info,
349 1.1 riastrad int plane)
350 1.1 riastrad {
351 1.1 riastrad if (!info || plane < 0 || plane >= info->num_planes)
352 1.1 riastrad return 0;
353 1.1 riastrad
354 1.1 riastrad if (!info->block_w[plane])
355 1.1 riastrad return 1;
356 1.1 riastrad return info->block_w[plane];
357 1.1 riastrad }
358 1.1 riastrad EXPORT_SYMBOL(drm_format_info_block_width);
359 1.1 riastrad
360 1.1 riastrad /**
361 1.1 riastrad * drm_format_info_block_height - height in pixels of a block
362 1.1 riastrad * @info: pixel format info
363 1.1 riastrad * @plane: plane index
364 1.1 riastrad *
365 1.1 riastrad * Returns:
366 1.1 riastrad * The height in pixels of a block, depending on the plane index.
367 1.1 riastrad */
368 1.1 riastrad unsigned int drm_format_info_block_height(const struct drm_format_info *info,
369 1.1 riastrad int plane)
370 1.1 riastrad {
371 1.1 riastrad if (!info || plane < 0 || plane >= info->num_planes)
372 1.1 riastrad return 0;
373 1.1 riastrad
374 1.1 riastrad if (!info->block_h[plane])
375 1.1 riastrad return 1;
376 1.1 riastrad return info->block_h[plane];
377 1.1 riastrad }
378 1.1 riastrad EXPORT_SYMBOL(drm_format_info_block_height);
379 1.1 riastrad
380 1.1 riastrad /**
381 1.1 riastrad * drm_format_info_min_pitch - computes the minimum required pitch in bytes
382 1.1 riastrad * @info: pixel format info
383 1.1 riastrad * @plane: plane index
384 1.1 riastrad * @buffer_width: buffer width in pixels
385 1.1 riastrad *
386 1.1 riastrad * Returns:
387 1.1 riastrad * The minimum required pitch in bytes for a buffer by taking into consideration
388 1.1 riastrad * the pixel format information and the buffer width.
389 1.1 riastrad */
390 1.1 riastrad uint64_t drm_format_info_min_pitch(const struct drm_format_info *info,
391 1.1 riastrad int plane, unsigned int buffer_width)
392 1.1 riastrad {
393 1.1 riastrad if (!info || plane < 0 || plane >= info->num_planes)
394 1.1 riastrad return 0;
395 1.1 riastrad
396 1.1 riastrad return DIV_ROUND_UP_ULL((u64)buffer_width * info->char_per_block[plane],
397 1.1 riastrad drm_format_info_block_width(info, plane) *
398 1.1 riastrad drm_format_info_block_height(info, plane));
399 1.1 riastrad }
400 1.1 riastrad EXPORT_SYMBOL(drm_format_info_min_pitch);
401