1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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/drmP.h>
31#include <drm/drm_fourcc.h>
32
33static char printable_char(int c)
34{
35 return isascii(c) && isprint(c) ? c : '?';
36}
37
38
39
40
41
42
43
44
45
46uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
47{
48 uint32_t fmt;
49
50 switch (bpp) {
51 case 8:
52 fmt = DRM_FORMAT_C8;
53 break;
54 case 16:
55 if (depth == 15)
56 fmt = DRM_FORMAT_XRGB1555;
57 else
58 fmt = DRM_FORMAT_RGB565;
59 break;
60 case 24:
61 fmt = DRM_FORMAT_RGB888;
62 break;
63 case 32:
64 if (depth == 24)
65 fmt = DRM_FORMAT_XRGB8888;
66 else if (depth == 30)
67 fmt = DRM_FORMAT_XRGB2101010;
68 else
69 fmt = DRM_FORMAT_ARGB8888;
70 break;
71 default:
72 DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n");
73 fmt = DRM_FORMAT_XRGB8888;
74 break;
75 }
76
77 return fmt;
78}
79EXPORT_SYMBOL(drm_mode_legacy_fb_format);
80
81
82
83
84
85
86
87
88char *drm_get_format_name(uint32_t format)
89{
90 char *buf = kmalloc(32, GFP_KERNEL);
91
92 snprintf(buf, 32,
93 "%c%c%c%c %s-endian (0x%08x)",
94 printable_char(format & 0xff),
95 printable_char((format >> 8) & 0xff),
96 printable_char((format >> 16) & 0xff),
97 printable_char((format >> 24) & 0x7f),
98 format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
99 format);
100
101 return buf;
102}
103EXPORT_SYMBOL(drm_get_format_name);
104
105
106
107
108
109
110
111
112
113
114void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
115 int *bpp)
116{
117 char *format_name;
118
119 switch (format) {
120 case DRM_FORMAT_C8:
121 case DRM_FORMAT_RGB332:
122 case DRM_FORMAT_BGR233:
123 *depth = 8;
124 *bpp = 8;
125 break;
126 case DRM_FORMAT_XRGB1555:
127 case DRM_FORMAT_XBGR1555:
128 case DRM_FORMAT_RGBX5551:
129 case DRM_FORMAT_BGRX5551:
130 case DRM_FORMAT_ARGB1555:
131 case DRM_FORMAT_ABGR1555:
132 case DRM_FORMAT_RGBA5551:
133 case DRM_FORMAT_BGRA5551:
134 *depth = 15;
135 *bpp = 16;
136 break;
137 case DRM_FORMAT_RGB565:
138 case DRM_FORMAT_BGR565:
139 *depth = 16;
140 *bpp = 16;
141 break;
142 case DRM_FORMAT_RGB888:
143 case DRM_FORMAT_BGR888:
144 *depth = 24;
145 *bpp = 24;
146 break;
147 case DRM_FORMAT_XRGB8888:
148 case DRM_FORMAT_XBGR8888:
149 case DRM_FORMAT_RGBX8888:
150 case DRM_FORMAT_BGRX8888:
151 *depth = 24;
152 *bpp = 32;
153 break;
154 case DRM_FORMAT_XRGB2101010:
155 case DRM_FORMAT_XBGR2101010:
156 case DRM_FORMAT_RGBX1010102:
157 case DRM_FORMAT_BGRX1010102:
158 case DRM_FORMAT_ARGB2101010:
159 case DRM_FORMAT_ABGR2101010:
160 case DRM_FORMAT_RGBA1010102:
161 case DRM_FORMAT_BGRA1010102:
162 *depth = 30;
163 *bpp = 32;
164 break;
165 case DRM_FORMAT_ARGB8888:
166 case DRM_FORMAT_ABGR8888:
167 case DRM_FORMAT_RGBA8888:
168 case DRM_FORMAT_BGRA8888:
169 *depth = 32;
170 *bpp = 32;
171 break;
172 default:
173 format_name = drm_get_format_name(format);
174 DRM_DEBUG_KMS("unsupported pixel format %s\n", format_name);
175 kfree(format_name);
176 *depth = 0;
177 *bpp = 0;
178 break;
179 }
180}
181EXPORT_SYMBOL(drm_fb_get_bpp_depth);
182
183
184
185
186
187
188
189
190int drm_format_num_planes(uint32_t format)
191{
192 switch (format) {
193 case DRM_FORMAT_YUV410:
194 case DRM_FORMAT_YVU410:
195 case DRM_FORMAT_YUV411:
196 case DRM_FORMAT_YVU411:
197 case DRM_FORMAT_YUV420:
198 case DRM_FORMAT_YVU420:
199 case DRM_FORMAT_YUV422:
200 case DRM_FORMAT_YVU422:
201 case DRM_FORMAT_YUV444:
202 case DRM_FORMAT_YVU444:
203 return 3;
204 case DRM_FORMAT_NV12:
205 case DRM_FORMAT_NV21:
206 case DRM_FORMAT_NV16:
207 case DRM_FORMAT_NV61:
208 case DRM_FORMAT_NV24:
209 case DRM_FORMAT_NV42:
210 return 2;
211 default:
212 return 1;
213 }
214}
215EXPORT_SYMBOL(drm_format_num_planes);
216
217
218
219
220
221
222
223
224
225int drm_format_plane_cpp(uint32_t format, int plane)
226{
227 unsigned int depth;
228 int bpp;
229
230 if (plane >= drm_format_num_planes(format))
231 return 0;
232
233 switch (format) {
234 case DRM_FORMAT_YUYV:
235 case DRM_FORMAT_YVYU:
236 case DRM_FORMAT_UYVY:
237 case DRM_FORMAT_VYUY:
238 return 2;
239 case DRM_FORMAT_NV12:
240 case DRM_FORMAT_NV21:
241 case DRM_FORMAT_NV16:
242 case DRM_FORMAT_NV61:
243 case DRM_FORMAT_NV24:
244 case DRM_FORMAT_NV42:
245 return plane ? 2 : 1;
246 case DRM_FORMAT_YUV410:
247 case DRM_FORMAT_YVU410:
248 case DRM_FORMAT_YUV411:
249 case DRM_FORMAT_YVU411:
250 case DRM_FORMAT_YUV420:
251 case DRM_FORMAT_YVU420:
252 case DRM_FORMAT_YUV422:
253 case DRM_FORMAT_YVU422:
254 case DRM_FORMAT_YUV444:
255 case DRM_FORMAT_YVU444:
256 return 1;
257 default:
258 drm_fb_get_bpp_depth(format, &depth, &bpp);
259 return bpp >> 3;
260 }
261}
262EXPORT_SYMBOL(drm_format_plane_cpp);
263
264
265
266
267
268
269
270
271
272int drm_format_horz_chroma_subsampling(uint32_t format)
273{
274 switch (format) {
275 case DRM_FORMAT_YUV411:
276 case DRM_FORMAT_YVU411:
277 case DRM_FORMAT_YUV410:
278 case DRM_FORMAT_YVU410:
279 return 4;
280 case DRM_FORMAT_YUYV:
281 case DRM_FORMAT_YVYU:
282 case DRM_FORMAT_UYVY:
283 case DRM_FORMAT_VYUY:
284 case DRM_FORMAT_NV12:
285 case DRM_FORMAT_NV21:
286 case DRM_FORMAT_NV16:
287 case DRM_FORMAT_NV61:
288 case DRM_FORMAT_YUV422:
289 case DRM_FORMAT_YVU422:
290 case DRM_FORMAT_YUV420:
291 case DRM_FORMAT_YVU420:
292 return 2;
293 default:
294 return 1;
295 }
296}
297EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
298
299
300
301
302
303
304
305
306
307int drm_format_vert_chroma_subsampling(uint32_t format)
308{
309 switch (format) {
310 case DRM_FORMAT_YUV410:
311 case DRM_FORMAT_YVU410:
312 return 4;
313 case DRM_FORMAT_YUV420:
314 case DRM_FORMAT_YVU420:
315 case DRM_FORMAT_NV12:
316 case DRM_FORMAT_NV21:
317 return 2;
318 default:
319 return 1;
320 }
321}
322EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
323
324
325
326
327
328
329
330
331
332
333int drm_format_plane_width(int width, uint32_t format, int plane)
334{
335 if (plane >= drm_format_num_planes(format))
336 return 0;
337
338 if (plane == 0)
339 return width;
340
341 return width / drm_format_horz_chroma_subsampling(format);
342}
343EXPORT_SYMBOL(drm_format_plane_width);
344
345
346
347
348
349
350
351
352
353
354int drm_format_plane_height(int height, uint32_t format, int plane)
355{
356 if (plane >= drm_format_num_planes(format))
357 return 0;
358
359 if (plane == 0)
360 return height;
361
362 return height / drm_format_vert_chroma_subsampling(format);
363}
364EXPORT_SYMBOL(drm_format_plane_height);
365