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