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 
printable_char(int c)33 static char printable_char(int c)
34 {
35     return isascii(c) && isprint(c) ? c : '?';
36 }
37 
38 /**
39  * drm_mode_legacy_fb_format - compute drm fourcc code from legacy description
40  * @bpp: bits per pixels
41  * @depth: bit depth per pixel
42  *
43  * Computes a drm fourcc pixel format code for the given @bpp/@depth values.
44  * Useful in fbdev emulation code, since that deals in those values.
45  */
drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)46 uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
47 {
48     uint32_t fmt = DRM_FORMAT_INVALID;
49 
50     switch (bpp) {
51         case 0x8:
52             if (depth == 0x8) {
53                 fmt = DRM_FORMAT_C8;
54             }
55             break;
56 
57         case 0x10:
58             switch (depth) {
59                 case 0xf:
60                     fmt = DRM_FORMAT_XRGB1555;
61                     break;
62                 case 0x10:
63                     fmt = DRM_FORMAT_RGB565;
64                     break;
65                 default:
66                     break;
67             }
68             break;
69 
70         case 0x18:
71             if (depth == 0x18) {
72                 fmt = DRM_FORMAT_RGB888;
73             }
74             break;
75 
76         case 0x20:
77             switch (depth) {
78                 case 0x18:
79                     fmt = DRM_FORMAT_XRGB8888;
80                     break;
81                 case 0x1e:
82                     fmt = DRM_FORMAT_XRGB2101010;
83                     break;
84                 case 0x20:
85                     fmt = DRM_FORMAT_ARGB8888;
86                     break;
87                 default:
88                     break;
89             }
90             break;
91 
92         default:
93             break;
94     }
95 
96     return fmt;
97 }
98 EXPORT_SYMBOL(drm_mode_legacy_fb_format);
99 
100 /**
101  * drm_driver_legacy_fb_format - compute drm fourcc code from legacy description
102  * @dev: DRM device
103  * @bpp: bits per pixels
104  * @depth: bit depth per pixel
105  *
106  * Computes a drm fourcc pixel format code for the given @bpp/@depth values.
107  * Unlike drm_mode_legacy_fb_format() this looks at the drivers mode_config,
108  * and depending on the &drm_mode_config.quirk_addfb_prefer_host_byte_order flag
109  * it returns little endian byte order or host byte order framebuffer formats.
110  */
drm_driver_legacy_fb_format(struct drm_device *dev, uint32_t bpp, uint32_t depth)111 uint32_t drm_driver_legacy_fb_format(struct drm_device *dev, uint32_t bpp, uint32_t depth)
112 {
113     uint32_t fmt = drm_mode_legacy_fb_format(bpp, depth);
114 
115     if (dev->mode_config.quirk_addfb_prefer_host_byte_order) {
116         if (fmt == DRM_FORMAT_XRGB8888) {
117             fmt = DRM_FORMAT_HOST_XRGB8888;
118         }
119         if (fmt == DRM_FORMAT_ARGB8888) {
120             fmt = DRM_FORMAT_HOST_ARGB8888;
121         }
122         if (fmt == DRM_FORMAT_RGB565) {
123             fmt = DRM_FORMAT_HOST_RGB565;
124         }
125         if (fmt == DRM_FORMAT_XRGB1555) {
126             fmt = DRM_FORMAT_HOST_XRGB1555;
127         }
128     }
129 
130     if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp && fmt == DRM_FORMAT_XRGB2101010) {
131         fmt = DRM_FORMAT_XBGR2101010;
132     }
133 
134     return fmt;
135 }
136 EXPORT_SYMBOL(drm_driver_legacy_fb_format);
137 
138 /**
139  * drm_get_format_name - fill a string with a drm fourcc format's name
140  * @format: format to compute name of
141  * @buf: caller-supplied buffer
142  */
drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf)143 const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf)
144 {
145     int ret = 0;
146     ret = snprintf(buf->str, sizeof(buf->str), "%c%c%c%c %s-endian (0x%08x)", printable_char(format & 0xff),
147              printable_char((format >> 0x8) & 0xff), printable_char((format >> 0x10) & 0xff),
148              printable_char((format >> 0x18) & 0x7f), format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little", format);
149 
150     return buf->str;
151 }
152 EXPORT_SYMBOL(drm_get_format_name);
153 
154 /*
155  * Internal function to query information for a given format. See
156  * drm_format_info() for the public API.
157  */
__drm_format_info(u32 format)158 const struct drm_format_info *__drm_format_info(u32 format)
159 {
160     static const struct drm_format_info formats[] = {
161         {.format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = {1, 0, 0}, .hsub = 1, .vsub = 1},
162         {.format = DRM_FORMAT_RGB332, .depth = 8, .num_planes = 1, .cpp = {1, 0, 0}, .hsub = 1, .vsub = 1},
163         {.format = DRM_FORMAT_BGR233, .depth = 8, .num_planes = 1, .cpp = {1, 0, 0}, .hsub = 1, .vsub = 1},
164         {.format = DRM_FORMAT_XRGB4444, .depth = 0, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
165         {.format = DRM_FORMAT_XBGR4444, .depth = 0, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
166         {.format = DRM_FORMAT_RGBX4444, .depth = 0, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
167         {.format = DRM_FORMAT_BGRX4444, .depth = 0, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
168         {.format = DRM_FORMAT_ARGB4444,
169          .depth = 0,
170          .num_planes = 1,
171          .cpp = {2, 0, 0},
172          .hsub = 1,
173          .vsub = 1,
174          .has_alpha = true},
175         {.format = DRM_FORMAT_ABGR4444,
176          .depth = 0,
177          .num_planes = 1,
178          .cpp = {2, 0, 0},
179          .hsub = 1,
180          .vsub = 1,
181          .has_alpha = true},
182         {.format = DRM_FORMAT_RGBA4444,
183          .depth = 0,
184          .num_planes = 1,
185          .cpp = {2, 0, 0},
186          .hsub = 1,
187          .vsub = 1,
188          .has_alpha = true},
189         {.format = DRM_FORMAT_BGRA4444,
190          .depth = 0,
191          .num_planes = 1,
192          .cpp = {2, 0, 0},
193          .hsub = 1,
194          .vsub = 1,
195          .has_alpha = true},
196         {.format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
197         {.format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
198         {.format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
199         {.format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
200         {.format = DRM_FORMAT_ARGB1555,
201          .depth = 15,
202          .num_planes = 1,
203          .cpp = {2, 0, 0},
204          .hsub = 1,
205          .vsub = 1,
206          .has_alpha = true},
207         {.format = DRM_FORMAT_ABGR1555,
208          .depth = 15,
209          .num_planes = 1,
210          .cpp = {2, 0, 0},
211          .hsub = 1,
212          .vsub = 1,
213          .has_alpha = true},
214         {.format = DRM_FORMAT_RGBA5551,
215          .depth = 15,
216          .num_planes = 1,
217          .cpp = {2, 0, 0},
218          .hsub = 1,
219          .vsub = 1,
220          .has_alpha = true},
221         {.format = DRM_FORMAT_BGRA5551,
222          .depth = 15,
223          .num_planes = 1,
224          .cpp = {2, 0, 0},
225          .hsub = 1,
226          .vsub = 1,
227          .has_alpha = true},
228         {.format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
229         {.format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = {2, 0, 0}, .hsub = 1, .vsub = 1},
230         {.format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = {3, 0, 0}, .hsub = 1, .vsub = 1},
231         {.format = DRM_FORMAT_BGR888, .depth = 24, .num_planes = 1, .cpp = {3, 0, 0}, .hsub = 1, .vsub = 1},
232         {.format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
233         {.format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
234         {.format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
235         {.format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
236         {.format = DRM_FORMAT_RGB565_A8,
237          .depth = 24,
238          .num_planes = 2,
239          .cpp = {2, 1, 0},
240          .hsub = 1,
241          .vsub = 1,
242          .has_alpha = true},
243         {.format = DRM_FORMAT_BGR565_A8,
244          .depth = 24,
245          .num_planes = 2,
246          .cpp = {2, 1, 0},
247          .hsub = 1,
248          .vsub = 1,
249          .has_alpha = true},
250         {.format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
251         {.format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
252         {.format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
253         {.format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = {4, 0, 0}, .hsub = 1, .vsub = 1},
254         {.format = DRM_FORMAT_ARGB2101010,
255          .depth = 30,
256          .num_planes = 1,
257          .cpp = {4, 0, 0},
258          .hsub = 1,
259          .vsub = 1,
260          .has_alpha = true},
261         {.format = DRM_FORMAT_ABGR2101010,
262          .depth = 30,
263          .num_planes = 1,
264          .cpp = {4, 0, 0},
265          .hsub = 1,
266          .vsub = 1,
267          .has_alpha = true},
268         {.format = DRM_FORMAT_RGBA1010102,
269          .depth = 30,
270          .num_planes = 1,
271          .cpp = {4, 0, 0},
272          .hsub = 1,
273          .vsub = 1,
274          .has_alpha = true},
275         {.format = DRM_FORMAT_BGRA1010102,
276          .depth = 30,
277          .num_planes = 1,
278          .cpp = {4, 0, 0},
279          .hsub = 1,
280          .vsub = 1,
281          .has_alpha = true},
282         {.format = DRM_FORMAT_ARGB8888,
283          .depth = 32,
284          .num_planes = 1,
285          .cpp = {4, 0, 0},
286          .hsub = 1,
287          .vsub = 1,
288          .has_alpha = true},
289         {.format = DRM_FORMAT_ABGR8888,
290          .depth = 32,
291          .num_planes = 1,
292          .cpp = {4, 0, 0},
293          .hsub = 1,
294          .vsub = 1,
295          .has_alpha = true},
296         {.format = DRM_FORMAT_RGBA8888,
297          .depth = 32,
298          .num_planes = 1,
299          .cpp = {4, 0, 0},
300          .hsub = 1,
301          .vsub = 1,
302          .has_alpha = true},
303         {.format = DRM_FORMAT_BGRA8888,
304          .depth = 32,
305          .num_planes = 1,
306          .cpp = {4, 0, 0},
307          .hsub = 1,
308          .vsub = 1,
309          .has_alpha = true},
310         {.format = DRM_FORMAT_XRGB16161616F, .depth = 0, .num_planes = 1, .cpp = {8, 0, 0}, .hsub = 1, .vsub = 1},
311         {.format = DRM_FORMAT_XBGR16161616F, .depth = 0, .num_planes = 1, .cpp = {8, 0, 0}, .hsub = 1, .vsub = 1},
312         {.format = DRM_FORMAT_ARGB16161616F,
313          .depth = 0,
314          .num_planes = 1,
315          .cpp = {8, 0, 0},
316          .hsub = 1,
317          .vsub = 1,
318          .has_alpha = true},
319         {.format = DRM_FORMAT_ABGR16161616F,
320          .depth = 0,
321          .num_planes = 1,
322          .cpp = {8, 0, 0},
323          .hsub = 1,
324          .vsub = 1,
325          .has_alpha = true},
326         {.format = DRM_FORMAT_RGB888_A8,
327          .depth = 32,
328          .num_planes = 2,
329          .cpp = {3, 1, 0},
330          .hsub = 1,
331          .vsub = 1,
332          .has_alpha = true},
333         {.format = DRM_FORMAT_BGR888_A8,
334          .depth = 32,
335          .num_planes = 2,
336          .cpp = {3, 1, 0},
337          .hsub = 1,
338          .vsub = 1,
339          .has_alpha = true},
340         {.format = DRM_FORMAT_XRGB8888_A8,
341          .depth = 32,
342          .num_planes = 2,
343          .cpp = {4, 1, 0},
344          .hsub = 1,
345          .vsub = 1,
346          .has_alpha = true},
347         {.format = DRM_FORMAT_XBGR8888_A8,
348          .depth = 32,
349          .num_planes = 2,
350          .cpp = {4, 1, 0},
351          .hsub = 1,
352          .vsub = 1,
353          .has_alpha = true},
354         {.format = DRM_FORMAT_RGBX8888_A8,
355          .depth = 32,
356          .num_planes = 2,
357          .cpp = {4, 1, 0},
358          .hsub = 1,
359          .vsub = 1,
360          .has_alpha = true},
361         {.format = DRM_FORMAT_BGRX8888_A8,
362          .depth = 32,
363          .num_planes = 2,
364          .cpp = {4, 1, 0},
365          .hsub = 1,
366          .vsub = 1,
367          .has_alpha = true},
368         {.format = DRM_FORMAT_YUV410,
369          .depth = 0,
370          .num_planes = 3,
371          .cpp = {1, 1, 1},
372          .hsub = 4,
373          .vsub = 4,
374          .is_yuv = true},
375         {.format = DRM_FORMAT_YVU410,
376          .depth = 0,
377          .num_planes = 3,
378          .cpp = {1, 1, 1},
379          .hsub = 4,
380          .vsub = 4,
381          .is_yuv = true},
382         {.format = DRM_FORMAT_YUV411,
383          .depth = 0,
384          .num_planes = 3,
385          .cpp = {1, 1, 1},
386          .hsub = 4,
387          .vsub = 1,
388          .is_yuv = true},
389         {.format = DRM_FORMAT_YVU411,
390          .depth = 0,
391          .num_planes = 3,
392          .cpp = {1, 1, 1},
393          .hsub = 4,
394          .vsub = 1,
395          .is_yuv = true},
396         {.format = DRM_FORMAT_YUV420,
397          .depth = 0,
398          .num_planes = 3,
399          .cpp = {1, 1, 1},
400          .hsub = 2,
401          .vsub = 2,
402          .is_yuv = true},
403         {.format = DRM_FORMAT_YVU420,
404          .depth = 0,
405          .num_planes = 3,
406          .cpp = {1, 1, 1},
407          .hsub = 2,
408          .vsub = 2,
409          .is_yuv = true},
410         {.format = DRM_FORMAT_YUV422,
411          .depth = 0,
412          .num_planes = 3,
413          .cpp = {1, 1, 1},
414          .hsub = 2,
415          .vsub = 1,
416          .is_yuv = true},
417         {.format = DRM_FORMAT_YVU422,
418          .depth = 0,
419          .num_planes = 3,
420          .cpp = {1, 1, 1},
421          .hsub = 2,
422          .vsub = 1,
423          .is_yuv = true},
424         {.format = DRM_FORMAT_YUV444,
425          .depth = 0,
426          .num_planes = 3,
427          .cpp = {1, 1, 1},
428          .hsub = 1,
429          .vsub = 1,
430          .is_yuv = true},
431         {.format = DRM_FORMAT_YVU444,
432          .depth = 0,
433          .num_planes = 3,
434          .cpp = {1, 1, 1},
435          .hsub = 1,
436          .vsub = 1,
437          .is_yuv = true},
438         {.format = DRM_FORMAT_NV12,
439          .depth = 0,
440          .num_planes = 2,
441          .cpp = {1, 2, 0},
442          .hsub = 2,
443          .vsub = 2,
444          .is_yuv = true},
445         {.format = DRM_FORMAT_NV21,
446          .depth = 0,
447          .num_planes = 2,
448          .cpp = {1, 2, 0},
449          .hsub = 2,
450          .vsub = 2,
451          .is_yuv = true},
452         {.format = DRM_FORMAT_NV16,
453          .depth = 0,
454          .num_planes = 2,
455          .cpp = {1, 2, 0},
456          .hsub = 2,
457          .vsub = 1,
458          .is_yuv = true},
459         {.format = DRM_FORMAT_NV61,
460          .depth = 0,
461          .num_planes = 2,
462          .cpp = {1, 2, 0},
463          .hsub = 2,
464          .vsub = 1,
465          .is_yuv = true},
466         {.format = DRM_FORMAT_NV24,
467          .depth = 0,
468          .num_planes = 2,
469          .cpp = {1, 2, 0},
470          .hsub = 1,
471          .vsub = 1,
472          .is_yuv = true},
473         {.format = DRM_FORMAT_NV42,
474          .depth = 0,
475          .num_planes = 2,
476          .cpp = {1, 2, 0},
477          .hsub = 1,
478          .vsub = 1,
479          .is_yuv = true},
480         {.format = DRM_FORMAT_YUYV,
481          .depth = 0,
482          .num_planes = 1,
483          .cpp = {2, 0, 0},
484          .hsub = 2,
485          .vsub = 1,
486          .is_yuv = true},
487         {.format = DRM_FORMAT_YVYU,
488          .depth = 0,
489          .num_planes = 1,
490          .cpp = {2, 0, 0},
491          .hsub = 2,
492          .vsub = 1,
493          .is_yuv = true},
494         {.format = DRM_FORMAT_UYVY,
495          .depth = 0,
496          .num_planes = 1,
497          .cpp = {2, 0, 0},
498          .hsub = 2,
499          .vsub = 1,
500          .is_yuv = true},
501         {.format = DRM_FORMAT_VYUY,
502          .depth = 0,
503          .num_planes = 1,
504          .cpp = {2, 0, 0},
505          .hsub = 2,
506          .vsub = 1,
507          .is_yuv = true},
508         {.format = DRM_FORMAT_XYUV8888,
509          .depth = 0,
510          .num_planes = 1,
511          .cpp = {4, 0, 0},
512          .hsub = 1,
513          .vsub = 1,
514          .is_yuv = true},
515         {.format = DRM_FORMAT_VUY888,
516          .depth = 0,
517          .num_planes = 1,
518          .cpp = {3, 0, 0},
519          .hsub = 1,
520          .vsub = 1,
521          .is_yuv = true},
522         {.format = DRM_FORMAT_AYUV,
523          .depth = 0,
524          .num_planes = 1,
525          .cpp = {4, 0, 0},
526          .hsub = 1,
527          .vsub = 1,
528          .has_alpha = true,
529          .is_yuv = true},
530         {.format = DRM_FORMAT_Y210,
531          .depth = 0,
532          .num_planes = 1,
533          .cpp = {4, 0, 0},
534          .hsub = 2,
535          .vsub = 1,
536          .is_yuv = true},
537         {.format = DRM_FORMAT_Y212,
538          .depth = 0,
539          .num_planes = 1,
540          .cpp = {4, 0, 0},
541          .hsub = 2,
542          .vsub = 1,
543          .is_yuv = true},
544         {.format = DRM_FORMAT_Y216,
545          .depth = 0,
546          .num_planes = 1,
547          .cpp = {4, 0, 0},
548          .hsub = 2,
549          .vsub = 1,
550          .is_yuv = true},
551         {.format = DRM_FORMAT_Y410,
552          .depth = 0,
553          .num_planes = 1,
554          .cpp = {4, 0, 0},
555          .hsub = 1,
556          .vsub = 1,
557          .has_alpha = true,
558          .is_yuv = true},
559         {.format = DRM_FORMAT_Y412,
560          .depth = 0,
561          .num_planes = 1,
562          .cpp = {8, 0, 0},
563          .hsub = 1,
564          .vsub = 1,
565          .has_alpha = true,
566          .is_yuv = true},
567         {.format = DRM_FORMAT_Y416,
568          .depth = 0,
569          .num_planes = 1,
570          .cpp = {8, 0, 0},
571          .hsub = 1,
572          .vsub = 1,
573          .has_alpha = true,
574          .is_yuv = true},
575         {.format = DRM_FORMAT_XVYU2101010,
576          .depth = 0,
577          .num_planes = 1,
578          .cpp = {4, 0, 0},
579          .hsub = 1,
580          .vsub = 1,
581          .is_yuv = true},
582         {.format = DRM_FORMAT_XVYU12_16161616,
583          .depth = 0,
584          .num_planes = 1,
585          .cpp = {8, 0, 0},
586          .hsub = 1,
587          .vsub = 1,
588          .is_yuv = true},
589         {.format = DRM_FORMAT_XVYU16161616,
590          .depth = 0,
591          .num_planes = 1,
592          .cpp = {8, 0, 0},
593          .hsub = 1,
594          .vsub = 1,
595          .is_yuv = true},
596         {.format = DRM_FORMAT_Y0L0,
597          .depth = 0,
598          .num_planes = 1,
599          .char_per_block = {8, 0, 0},
600          .block_w = {2, 0, 0},
601          .block_h = {2, 0, 0},
602          .hsub = 2,
603          .vsub = 2,
604          .has_alpha = true,
605          .is_yuv = true},
606         {.format = DRM_FORMAT_X0L0,
607          .depth = 0,
608          .num_planes = 1,
609          .char_per_block = {8, 0, 0},
610          .block_w = {2, 0, 0},
611          .block_h = {2, 0, 0},
612          .hsub = 2,
613          .vsub = 2,
614          .is_yuv = true},
615         {.format = DRM_FORMAT_Y0L2,
616          .depth = 0,
617          .num_planes = 1,
618          .char_per_block = {8, 0, 0},
619          .block_w = {2, 0, 0},
620          .block_h = {2, 0, 0},
621          .hsub = 2,
622          .vsub = 2,
623          .has_alpha = true,
624          .is_yuv = true},
625         {.format = DRM_FORMAT_X0L2,
626          .depth = 0,
627          .num_planes = 1,
628          .char_per_block = {8, 0, 0},
629          .block_w = {2, 0, 0},
630          .block_h = {2, 0, 0},
631          .hsub = 2,
632          .vsub = 2,
633          .is_yuv = true},
634         {.format = DRM_FORMAT_P010,
635          .depth = 0,
636          .num_planes = 2,
637          .char_per_block = {2, 4, 0},
638          .block_w = {1, 1, 0},
639          .block_h = {1, 1, 0},
640          .hsub = 2,
641          .vsub = 2,
642          .is_yuv = true},
643         {.format = DRM_FORMAT_P012,
644          .depth = 0,
645          .num_planes = 2,
646          .char_per_block = {2, 4, 0},
647          .block_w = {1, 1, 0},
648          .block_h = {1, 1, 0},
649          .hsub = 2,
650          .vsub = 2,
651          .is_yuv = true},
652         {.format = DRM_FORMAT_P016,
653          .depth = 0,
654          .num_planes = 2,
655          .char_per_block = {2, 4, 0},
656          .block_w = {1, 1, 0},
657          .block_h = {1, 1, 0},
658          .hsub = 2,
659          .vsub = 2,
660          .is_yuv = true},
661         {.format = DRM_FORMAT_P210,
662          .depth = 0,
663          .num_planes = 2,
664          .char_per_block = {2, 4, 0},
665          .block_w = {1, 1, 0},
666          .block_h = {1, 1, 0},
667          .hsub = 2,
668          .vsub = 1,
669          .is_yuv = true},
670         {.format = DRM_FORMAT_VUY101010,
671          .depth = 0,
672          .num_planes = 1,
673          .cpp = {0, 0, 0},
674          .hsub = 1,
675          .vsub = 1,
676          .is_yuv = true},
677         {.format = DRM_FORMAT_YUV420_8BIT,
678          .depth = 0,
679          .num_planes = 1,
680          .cpp = {0, 0, 0},
681          .hsub = 2,
682          .vsub = 2,
683          .is_yuv = true},
684         {.format = DRM_FORMAT_YUV420_10BIT,
685          .depth = 0,
686          .num_planes = 1,
687          .cpp = {0, 0, 0},
688          .hsub = 2,
689          .vsub = 2,
690          .is_yuv = true},
691         {.format = DRM_FORMAT_NV15,
692          .depth = 0,
693          .num_planes = 2,
694          .char_per_block = {5, 5, 0},
695          .block_w = {4, 2, 0},
696          .block_h = {1, 1, 0},
697          .hsub = 2,
698          .vsub = 2,
699          .is_yuv = true},
700 #ifdef CONFIG_NO_GKI
701         {.format = DRM_FORMAT_NV20,
702          .depth = 0,
703          .num_planes = 2,
704          .char_per_block = {5, 5, 0},
705          .block_w = {4, 2, 0},
706          .block_h = {1, 1, 0},
707          .hsub = 2,
708          .vsub = 1,
709          .is_yuv = true},
710         {.format = DRM_FORMAT_NV30,
711          .depth = 0,
712          .num_planes = 2,
713          .char_per_block = {5, 5, 0},
714          .block_w = {4, 2, 0},
715          .block_h = {1, 1, 0},
716          .hsub = 1,
717          .vsub = 1,
718          .is_yuv = true},
719 #endif
720         {.format = DRM_FORMAT_Q410,
721          .depth = 0,
722          .num_planes = 3,
723          .char_per_block = {2, 2, 2},
724          .block_w = {1, 1, 1},
725          .block_h = {1, 1, 1},
726          .hsub = 0,
727          .vsub = 0,
728          .is_yuv = true},
729         {.format = DRM_FORMAT_Q401,
730          .depth = 0,
731          .num_planes = 3,
732          .char_per_block = {2, 2, 2},
733          .block_w = {1, 1, 1},
734          .block_h = {1, 1, 1},
735          .hsub = 0,
736          .vsub = 0,
737          .is_yuv = true},
738     };
739 
740     unsigned int i;
741 
742     for (i = 0; i < ARRAY_SIZE(formats); ++i) {
743         if (formats[i].format == format) {
744             return &formats[i];
745         }
746     }
747 
748     return NULL;
749 }
750 
751 /**
752  * drm_format_info - query information for a given format
753  * @format: pixel format (DRM_FORMAT_*)
754  *
755  * The caller should only pass a supported pixel format to this function.
756  * Unsupported pixel formats will generate a warning in the kernel log.
757  *
758  * Returns:
759  * The instance of struct drm_format_info that describes the pixel format, or
760  * NULL if the format is unsupported.
761  */
drm_format_info(u32 format)762 const struct drm_format_info *drm_format_info(u32 format)
763 {
764     const struct drm_format_info *info;
765 
766     info = __drm_format_info(format);
767     WARN_ON(!info);
768     return info;
769 }
770 EXPORT_SYMBOL(drm_format_info);
771 
772 /**
773  * drm_get_format_info - query information for a given framebuffer configuration
774  * @dev: DRM device
775  * @mode_cmd: metadata from the userspace fb creation request
776  *
777  * Returns:
778  * The instance of struct drm_format_info that describes the pixel format, or
779  * NULL if the format is unsupported.
780  */
drm_get_format_info(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd)781 const struct drm_format_info *drm_get_format_info(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd)
782 {
783     const struct drm_format_info *info = NULL;
784 
785     if (dev->mode_config.funcs->get_format_info) {
786         info = dev->mode_config.funcs->get_format_info(mode_cmd);
787     }
788 
789     if (!info) {
790         info = drm_format_info(mode_cmd->pixel_format);
791     }
792 
793     return info;
794 }
795 EXPORT_SYMBOL(drm_get_format_info);
796 
797 /**
798  * drm_format_info_block_width - width in pixels of block.
799  * @info: pixel format info
800  * @plane: plane index
801  *
802  * Returns:
803  * The width in pixels of a block, depending on the plane index.
804  */
drm_format_info_block_width(const struct drm_format_info *info, int plane)805 unsigned int drm_format_info_block_width(const struct drm_format_info *info, int plane)
806 {
807     if (!info || plane < 0 || plane >= info->num_planes) {
808         return 0;
809     }
810 
811     if (!info->block_w[plane]) {
812         return 1;
813     }
814     return info->block_w[plane];
815 }
816 EXPORT_SYMBOL(drm_format_info_block_width);
817 
818 /**
819  * drm_format_info_block_height - height in pixels of a block
820  * @info: pixel format info
821  * @plane: plane index
822  *
823  * Returns:
824  * The height in pixels of a block, depending on the plane index.
825  */
drm_format_info_block_height(const struct drm_format_info *info, int plane)826 unsigned int drm_format_info_block_height(const struct drm_format_info *info, int plane)
827 {
828     if (!info || plane < 0 || plane >= info->num_planes) {
829         return 0;
830     }
831 
832     if (!info->block_h[plane]) {
833         return 1;
834     }
835     return info->block_h[plane];
836 }
837 EXPORT_SYMBOL(drm_format_info_block_height);
838 
839 /**
840  * drm_format_info_min_pitch - computes the minimum required pitch in bytes
841  * @info: pixel format info
842  * @plane: plane index
843  * @buffer_width: buffer width in pixels
844  *
845  * Returns:
846  * The minimum required pitch in bytes for a buffer by taking into consideration
847  * the pixel format information and the buffer width.
848  */
drm_format_info_min_pitch(const struct drm_format_info *info, int plane, unsigned int buffer_width)849 uint64_t drm_format_info_min_pitch(const struct drm_format_info *info, int plane, unsigned int buffer_width)
850 {
851     if (!info || plane < 0 || plane >= info->num_planes) {
852         return 0;
853     }
854 
855     return DIV_ROUND_UP_ULL((u64)buffer_width * info->char_per_block[plane],
856                             drm_format_info_block_width(info, plane) * drm_format_info_block_height(info, plane));
857 }
858 EXPORT_SYMBOL(drm_format_info_min_pitch);
859