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 | * Useful in fbdev emulation code, since that deals in those values. |
40 | */ |
41 | uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) |
42 | { |
43 | uint32_t fmt = DRM_FORMAT_INVALID; |
44 | |
45 | switch (bpp) { |
46 | case 1: |
47 | if (depth == 1) |
48 | fmt = DRM_FORMAT_C1; |
49 | break; |
50 | |
51 | case 2: |
52 | if (depth == 2) |
53 | fmt = DRM_FORMAT_C2; |
54 | break; |
55 | |
56 | case 4: |
57 | if (depth == 4) |
58 | fmt = DRM_FORMAT_C4; |
59 | break; |
60 | |
61 | case 8: |
62 | if (depth == 8) |
63 | fmt = DRM_FORMAT_C8; |
64 | break; |
65 | |
66 | case 16: |
67 | switch (depth) { |
68 | case 15: |
69 | fmt = DRM_FORMAT_XRGB1555; |
70 | break; |
71 | case 16: |
72 | fmt = DRM_FORMAT_RGB565; |
73 | break; |
74 | default: |
75 | break; |
76 | } |
77 | break; |
78 | |
79 | case 24: |
80 | if (depth == 24) |
81 | fmt = DRM_FORMAT_RGB888; |
82 | break; |
83 | |
84 | case 32: |
85 | switch (depth) { |
86 | case 24: |
87 | fmt = DRM_FORMAT_XRGB8888; |
88 | break; |
89 | case 30: |
90 | fmt = DRM_FORMAT_XRGB2101010; |
91 | break; |
92 | case 32: |
93 | fmt = DRM_FORMAT_ARGB8888; |
94 | break; |
95 | default: |
96 | break; |
97 | } |
98 | break; |
99 | |
100 | default: |
101 | break; |
102 | } |
103 | |
104 | return fmt; |
105 | } |
106 | EXPORT_SYMBOL(drm_mode_legacy_fb_format); |
107 | |
108 | /** |
109 | * drm_driver_legacy_fb_format - compute drm fourcc code from legacy description |
110 | * @dev: DRM device |
111 | * @bpp: bits per pixels |
112 | * @depth: bit depth per pixel |
113 | * |
114 | * Computes a drm fourcc pixel format code for the given @bpp/@depth values. |
115 | * Unlike drm_mode_legacy_fb_format() this looks at the drivers mode_config, |
116 | * and depending on the &drm_mode_config.quirk_addfb_prefer_host_byte_order flag |
117 | * it returns little endian byte order or host byte order framebuffer formats. |
118 | */ |
119 | uint32_t drm_driver_legacy_fb_format(struct drm_device *dev, |
120 | uint32_t bpp, uint32_t depth) |
121 | { |
122 | uint32_t fmt = drm_mode_legacy_fb_format(bpp, depth); |
123 | |
124 | if (dev->mode_config.quirk_addfb_prefer_host_byte_order) { |
125 | if (fmt == DRM_FORMAT_XRGB8888) |
126 | fmt = DRM_FORMAT_HOST_XRGB8888; |
127 | if (fmt == DRM_FORMAT_ARGB8888) |
128 | fmt = DRM_FORMAT_HOST_ARGB8888; |
129 | if (fmt == DRM_FORMAT_RGB565) |
130 | fmt = DRM_FORMAT_HOST_RGB565; |
131 | if (fmt == DRM_FORMAT_XRGB1555) |
132 | fmt = DRM_FORMAT_HOST_XRGB1555; |
133 | } |
134 | |
135 | if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp && |
136 | fmt == DRM_FORMAT_XRGB2101010) |
137 | fmt = DRM_FORMAT_XBGR2101010; |
138 | |
139 | return fmt; |
140 | } |
141 | EXPORT_SYMBOL(drm_driver_legacy_fb_format); |
142 | |
143 | /* |
144 | * Internal function to query information for a given format. See |
145 | * drm_format_info() for the public API. |
146 | */ |
147 | const struct drm_format_info *__drm_format_info(u32 format) |
148 | { |
149 | static const struct drm_format_info formats[] = { |
150 | { .format = DRM_FORMAT_C1, .depth = 1, .num_planes = 1, |
151 | .char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, |
152 | { .format = DRM_FORMAT_C2, .depth = 2, .num_planes = 1, |
153 | .char_per_block = { 1, }, .block_w = { 4, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, |
154 | { .format = DRM_FORMAT_C4, .depth = 4, .num_planes = 1, |
155 | .char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, |
156 | { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1, .is_color_indexed = true }, |
157 | { .format = DRM_FORMAT_D1, .depth = 1, .num_planes = 1, |
158 | .char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, |
159 | { .format = DRM_FORMAT_D2, .depth = 2, .num_planes = 1, |
160 | .char_per_block = { 1, }, .block_w = { 4, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, |
161 | { .format = DRM_FORMAT_D4, .depth = 4, .num_planes = 1, |
162 | .char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, |
163 | { .format = DRM_FORMAT_D8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, |
164 | { .format = DRM_FORMAT_R1, .depth = 1, .num_planes = 1, |
165 | .char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, |
166 | { .format = DRM_FORMAT_R2, .depth = 2, .num_planes = 1, |
167 | .char_per_block = { 1, }, .block_w = { 4, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, |
168 | { .format = DRM_FORMAT_R4, .depth = 4, .num_planes = 1, |
169 | .char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 }, |
170 | { .format = DRM_FORMAT_R8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, |
171 | { .format = DRM_FORMAT_R10, .depth = 10, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
172 | { .format = DRM_FORMAT_R12, .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
173 | { .format = DRM_FORMAT_RGB332, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, |
174 | { .format = DRM_FORMAT_BGR233, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, |
175 | { .format = DRM_FORMAT_XRGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
176 | { .format = DRM_FORMAT_XBGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
177 | { .format = DRM_FORMAT_RGBX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
178 | { .format = DRM_FORMAT_BGRX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
179 | { .format = DRM_FORMAT_ARGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
180 | { .format = DRM_FORMAT_ABGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
181 | { .format = DRM_FORMAT_RGBA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
182 | { .format = DRM_FORMAT_BGRA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
183 | { .format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
184 | { .format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
185 | { .format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
186 | { .format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
187 | { .format = DRM_FORMAT_ARGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
188 | { .format = DRM_FORMAT_ABGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
189 | { .format = DRM_FORMAT_RGBA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
190 | { .format = DRM_FORMAT_BGRA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
191 | { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
192 | { .format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
193 | #ifdef __BIG_ENDIAN |
194 | { .format = DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
195 | { .format = DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
196 | #endif |
197 | { .format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, |
198 | { .format = DRM_FORMAT_BGR888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, |
199 | { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, |
200 | { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, |
201 | { .format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, |
202 | { .format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, |
203 | { .format = DRM_FORMAT_RGB565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
204 | { .format = DRM_FORMAT_BGR565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
205 | { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, |
206 | { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, |
207 | { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, |
208 | { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, |
209 | { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
210 | { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
211 | { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
212 | { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
213 | { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
214 | { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
215 | { .format = DRM_FORMAT_RGBA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
216 | { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
217 | { .format = DRM_FORMAT_XRGB16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 }, |
218 | { .format = DRM_FORMAT_XBGR16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 }, |
219 | { .format = DRM_FORMAT_ARGB16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
220 | { .format = DRM_FORMAT_ABGR16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
221 | { .format = DRM_FORMAT_AXBXGXRX106106106106, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
222 | { .format = DRM_FORMAT_XRGB16161616, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 }, |
223 | { .format = DRM_FORMAT_XBGR16161616, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 }, |
224 | { .format = DRM_FORMAT_ARGB16161616, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
225 | { .format = DRM_FORMAT_ABGR16161616, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
226 | { .format = DRM_FORMAT_RGB888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
227 | { .format = DRM_FORMAT_BGR888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
228 | { .format = DRM_FORMAT_XRGB8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
229 | { .format = DRM_FORMAT_XBGR8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
230 | { .format = DRM_FORMAT_RGBX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
231 | { .format = DRM_FORMAT_BGRX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
232 | { .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true }, |
233 | { .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true }, |
234 | { .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true }, |
235 | { .format = DRM_FORMAT_YVU411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true }, |
236 | { .format = DRM_FORMAT_YUV420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true }, |
237 | { .format = DRM_FORMAT_YVU420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true }, |
238 | { .format = DRM_FORMAT_YUV422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true }, |
239 | { .format = DRM_FORMAT_YVU422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true }, |
240 | { .format = DRM_FORMAT_YUV444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true }, |
241 | { .format = DRM_FORMAT_YVU444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true }, |
242 | { .format = DRM_FORMAT_NV12, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true }, |
243 | { .format = DRM_FORMAT_NV21, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true }, |
244 | { .format = DRM_FORMAT_NV16, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, |
245 | { .format = DRM_FORMAT_NV61, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, |
246 | { .format = DRM_FORMAT_NV24, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, |
247 | { .format = DRM_FORMAT_NV42, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, |
248 | { .format = DRM_FORMAT_YUYV, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, |
249 | { .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, |
250 | { .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, |
251 | { .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, |
252 | { .format = DRM_FORMAT_XYUV8888, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, |
253 | { .format = DRM_FORMAT_VUY888, .depth = 0, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, |
254 | { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, |
255 | { .format = DRM_FORMAT_Y210, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, |
256 | { .format = DRM_FORMAT_Y212, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, |
257 | { .format = DRM_FORMAT_Y216, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, |
258 | { .format = DRM_FORMAT_Y410, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, |
259 | { .format = DRM_FORMAT_Y412, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, |
260 | { .format = DRM_FORMAT_Y416, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, |
261 | { .format = DRM_FORMAT_XVYU2101010, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, |
262 | { .format = DRM_FORMAT_XVYU12_16161616, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, |
263 | { .format = DRM_FORMAT_XVYU16161616, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, |
264 | { .format = DRM_FORMAT_Y0L0, .depth = 0, .num_planes = 1, |
265 | .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 }, |
266 | .hsub = 2, .vsub = 2, .has_alpha = true, .is_yuv = true }, |
267 | { .format = DRM_FORMAT_X0L0, .depth = 0, .num_planes = 1, |
268 | .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 }, |
269 | .hsub = 2, .vsub = 2, .is_yuv = true }, |
270 | { .format = DRM_FORMAT_Y0L2, .depth = 0, .num_planes = 1, |
271 | .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 }, |
272 | .hsub = 2, .vsub = 2, .has_alpha = true, .is_yuv = true }, |
273 | { .format = DRM_FORMAT_X0L2, .depth = 0, .num_planes = 1, |
274 | .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 }, |
275 | .hsub = 2, .vsub = 2, .is_yuv = true }, |
276 | { .format = DRM_FORMAT_P010, .depth = 0, .num_planes = 2, |
277 | .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, |
278 | .hsub = 2, .vsub = 2, .is_yuv = true}, |
279 | { .format = DRM_FORMAT_P012, .depth = 0, .num_planes = 2, |
280 | .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, |
281 | .hsub = 2, .vsub = 2, .is_yuv = true}, |
282 | { .format = DRM_FORMAT_P016, .depth = 0, .num_planes = 2, |
283 | .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, |
284 | .hsub = 2, .vsub = 2, .is_yuv = true}, |
285 | { .format = DRM_FORMAT_P210, .depth = 0, |
286 | .num_planes = 2, .char_per_block = { 2, 4, 0 }, |
287 | .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, |
288 | .vsub = 1, .is_yuv = true }, |
289 | { .format = DRM_FORMAT_VUY101010, .depth = 0, |
290 | .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 1, .vsub = 1, |
291 | .is_yuv = true }, |
292 | { .format = DRM_FORMAT_YUV420_8BIT, .depth = 0, |
293 | .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2, |
294 | .is_yuv = true }, |
295 | { .format = DRM_FORMAT_YUV420_10BIT, .depth = 0, |
296 | .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2, |
297 | .is_yuv = true }, |
298 | { .format = DRM_FORMAT_NV15, .depth = 0, |
299 | .num_planes = 2, .char_per_block = { 5, 5, 0 }, |
300 | .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, |
301 | .vsub = 2, .is_yuv = true }, |
302 | { .format = DRM_FORMAT_NV20, .depth = 0, |
303 | .num_planes = 2, .char_per_block = { 5, 5, 0 }, |
304 | .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, |
305 | .vsub = 1, .is_yuv = true }, |
306 | { .format = DRM_FORMAT_NV30, .depth = 0, |
307 | .num_planes = 2, .char_per_block = { 5, 5, 0 }, |
308 | .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 1, |
309 | .vsub = 1, .is_yuv = true }, |
310 | { .format = DRM_FORMAT_Q410, .depth = 0, |
311 | .num_planes = 3, .char_per_block = { 2, 2, 2 }, |
312 | .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 1, |
313 | .vsub = 1, .is_yuv = true }, |
314 | { .format = DRM_FORMAT_Q401, .depth = 0, |
315 | .num_planes = 3, .char_per_block = { 2, 2, 2 }, |
316 | .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 1, |
317 | .vsub = 1, .is_yuv = true }, |
318 | { .format = DRM_FORMAT_P030, .depth = 0, .num_planes = 2, |
319 | .char_per_block = { 4, 8, 0 }, .block_w = { 3, 3, 0 }, .block_h = { 1, 1, 0 }, |
320 | .hsub = 2, .vsub = 2, .is_yuv = true}, |
321 | }; |
322 | |
323 | unsigned int i; |
324 | |
325 | for (i = 0; i < ARRAY_SIZE(formats); ++i) { |
326 | if (formats[i].format == format) |
327 | return &formats[i]; |
328 | } |
329 | |
330 | return NULL; |
331 | } |
332 | |
333 | /** |
334 | * drm_format_info - query information for a given format |
335 | * @format: pixel format (DRM_FORMAT_*) |
336 | * |
337 | * The caller should only pass a supported pixel format to this function. |
338 | * Unsupported pixel formats will generate a warning in the kernel log. |
339 | * |
340 | * Returns: |
341 | * The instance of struct drm_format_info that describes the pixel format, or |
342 | * NULL if the format is unsupported. |
343 | */ |
344 | const struct drm_format_info *drm_format_info(u32 format) |
345 | { |
346 | const struct drm_format_info *info; |
347 | |
348 | info = __drm_format_info(format); |
349 | WARN_ON(!info); |
350 | return info; |
351 | } |
352 | EXPORT_SYMBOL(drm_format_info); |
353 | |
354 | /** |
355 | * drm_get_format_info - query information for a given framebuffer configuration |
356 | * @dev: DRM device |
357 | * @mode_cmd: metadata from the userspace fb creation request |
358 | * |
359 | * Returns: |
360 | * The instance of struct drm_format_info that describes the pixel format, or |
361 | * NULL if the format is unsupported. |
362 | */ |
363 | const struct drm_format_info * |
364 | drm_get_format_info(struct drm_device *dev, |
365 | const struct drm_mode_fb_cmd2 *mode_cmd) |
366 | { |
367 | const struct drm_format_info *info = NULL; |
368 | |
369 | if (dev->mode_config.funcs->get_format_info) |
370 | info = dev->mode_config.funcs->get_format_info(mode_cmd); |
371 | |
372 | if (!info) |
373 | info = drm_format_info(mode_cmd->pixel_format); |
374 | |
375 | return info; |
376 | } |
377 | EXPORT_SYMBOL(drm_get_format_info); |
378 | |
379 | /** |
380 | * drm_format_info_block_width - width in pixels of block. |
381 | * @info: pixel format info |
382 | * @plane: plane index |
383 | * |
384 | * Returns: |
385 | * The width in pixels of a block, depending on the plane index. |
386 | */ |
387 | unsigned int drm_format_info_block_width(const struct drm_format_info *info, |
388 | int plane) |
389 | { |
390 | if (!info || plane < 0 || plane >= info->num_planes) |
391 | return 0; |
392 | |
393 | if (!info->block_w[plane]) |
394 | return 1; |
395 | return info->block_w[plane]; |
396 | } |
397 | EXPORT_SYMBOL(drm_format_info_block_width); |
398 | |
399 | /** |
400 | * drm_format_info_block_height - height in pixels of a block |
401 | * @info: pixel format info |
402 | * @plane: plane index |
403 | * |
404 | * Returns: |
405 | * The height in pixels of a block, depending on the plane index. |
406 | */ |
407 | unsigned int drm_format_info_block_height(const struct drm_format_info *info, |
408 | int plane) |
409 | { |
410 | if (!info || plane < 0 || plane >= info->num_planes) |
411 | return 0; |
412 | |
413 | if (!info->block_h[plane]) |
414 | return 1; |
415 | return info->block_h[plane]; |
416 | } |
417 | EXPORT_SYMBOL(drm_format_info_block_height); |
418 | |
419 | /** |
420 | * drm_format_info_bpp - number of bits per pixel |
421 | * @info: pixel format info |
422 | * @plane: plane index |
423 | * |
424 | * Returns: |
425 | * The actual number of bits per pixel, depending on the plane index. |
426 | */ |
427 | unsigned int drm_format_info_bpp(const struct drm_format_info *info, int plane) |
428 | { |
429 | if (!info || plane < 0 || plane >= info->num_planes) |
430 | return 0; |
431 | |
432 | return info->char_per_block[plane] * 8 / |
433 | (drm_format_info_block_width(info, plane) * |
434 | drm_format_info_block_height(info, plane)); |
435 | } |
436 | EXPORT_SYMBOL(drm_format_info_bpp); |
437 | |
438 | /** |
439 | * drm_format_info_min_pitch - computes the minimum required pitch in bytes |
440 | * @info: pixel format info |
441 | * @plane: plane index |
442 | * @buffer_width: buffer width in pixels |
443 | * |
444 | * Returns: |
445 | * The minimum required pitch in bytes for a buffer by taking into consideration |
446 | * the pixel format information and the buffer width. |
447 | */ |
448 | uint64_t drm_format_info_min_pitch(const struct drm_format_info *info, |
449 | int plane, unsigned int buffer_width) |
450 | { |
451 | if (!info || plane < 0 || plane >= info->num_planes) |
452 | return 0; |
453 | |
454 | return DIV_ROUND_UP_ULL((u64)buffer_width * info->char_per_block[plane], |
455 | drm_format_info_block_width(info, plane) * |
456 | drm_format_info_block_height(info, plane)); |
457 | } |
458 | EXPORT_SYMBOL(drm_format_info_min_pitch); |
459 | |