Commit | Line | Data |
---|---|---|
ae4df11a LP |
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 | ||
0500c04e | 30 | #include <drm/drm_device.h> |
ae4df11a LP |
31 | #include <drm/drm_fourcc.h> |
32 | ||
33 | static char printable_char(int c) | |
34 | { | |
35 | return isascii(c) && isprint(c) ? c : '?'; | |
36 | } | |
37 | ||
ec5e3047 DV |
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 | */ | |
46 | uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) | |
47 | { | |
70109354 | 48 | uint32_t fmt = DRM_FORMAT_INVALID; |
ec5e3047 DV |
49 | |
50 | switch (bpp) { | |
51 | case 8: | |
70109354 CW |
52 | if (depth == 8) |
53 | fmt = DRM_FORMAT_C8; | |
ec5e3047 | 54 | break; |
70109354 | 55 | |
ec5e3047 | 56 | case 16: |
70109354 CW |
57 | switch (depth) { |
58 | case 15: | |
ec5e3047 | 59 | fmt = DRM_FORMAT_XRGB1555; |
70109354 CW |
60 | break; |
61 | case 16: | |
ec5e3047 | 62 | fmt = DRM_FORMAT_RGB565; |
70109354 CW |
63 | break; |
64 | default: | |
65 | break; | |
66 | } | |
ec5e3047 | 67 | break; |
70109354 | 68 | |
ec5e3047 | 69 | case 24: |
70109354 CW |
70 | if (depth == 24) |
71 | fmt = DRM_FORMAT_RGB888; | |
ec5e3047 | 72 | break; |
70109354 | 73 | |
ec5e3047 | 74 | case 32: |
70109354 CW |
75 | switch (depth) { |
76 | case 24: | |
ec5e3047 | 77 | fmt = DRM_FORMAT_XRGB8888; |
70109354 CW |
78 | break; |
79 | case 30: | |
ec5e3047 | 80 | fmt = DRM_FORMAT_XRGB2101010; |
70109354 CW |
81 | break; |
82 | case 32: | |
ec5e3047 | 83 | fmt = DRM_FORMAT_ARGB8888; |
70109354 CW |
84 | break; |
85 | default: | |
86 | break; | |
87 | } | |
ec5e3047 | 88 | break; |
70109354 | 89 | |
ec5e3047 | 90 | default: |
ec5e3047 DV |
91 | break; |
92 | } | |
93 | ||
94 | return fmt; | |
95 | } | |
96 | EXPORT_SYMBOL(drm_mode_legacy_fb_format); | |
97 | ||
059b5eb5 GH |
98 | /** |
99 | * drm_driver_legacy_fb_format - compute drm fourcc code from legacy description | |
4af67def | 100 | * @dev: DRM device |
059b5eb5 GH |
101 | * @bpp: bits per pixels |
102 | * @depth: bit depth per pixel | |
059b5eb5 GH |
103 | * |
104 | * Computes a drm fourcc pixel format code for the given @bpp/@depth values. | |
105 | * Unlike drm_mode_legacy_fb_format() this looks at the drivers mode_config, | |
4af67def DV |
106 | * and depending on the &drm_mode_config.quirk_addfb_prefer_host_byte_order flag |
107 | * it returns little endian byte order or host byte order framebuffer formats. | |
059b5eb5 GH |
108 | */ |
109 | uint32_t drm_driver_legacy_fb_format(struct drm_device *dev, | |
110 | uint32_t bpp, uint32_t depth) | |
111 | { | |
112 | uint32_t fmt = drm_mode_legacy_fb_format(bpp, depth); | |
113 | ||
114 | if (dev->mode_config.quirk_addfb_prefer_host_byte_order) { | |
115 | if (fmt == DRM_FORMAT_XRGB8888) | |
116 | fmt = DRM_FORMAT_HOST_XRGB8888; | |
117 | if (fmt == DRM_FORMAT_ARGB8888) | |
118 | fmt = DRM_FORMAT_HOST_ARGB8888; | |
119 | if (fmt == DRM_FORMAT_RGB565) | |
120 | fmt = DRM_FORMAT_HOST_RGB565; | |
121 | if (fmt == DRM_FORMAT_XRGB1555) | |
122 | fmt = DRM_FORMAT_HOST_XRGB1555; | |
123 | } | |
9dd3cb24 GH |
124 | |
125 | if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp && | |
126 | fmt == DRM_FORMAT_XRGB2101010) | |
127 | fmt = DRM_FORMAT_XBGR2101010; | |
128 | ||
059b5eb5 GH |
129 | return fmt; |
130 | } | |
131 | EXPORT_SYMBOL(drm_driver_legacy_fb_format); | |
132 | ||
ae4df11a | 133 | /** |
b3c11ac2 | 134 | * drm_get_format_name - fill a string with a drm fourcc format's name |
ae4df11a | 135 | * @format: format to compute name of |
b3c11ac2 | 136 | * @buf: caller-supplied buffer |
ae4df11a | 137 | */ |
b3c11ac2 | 138 | const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf) |
ae4df11a | 139 | { |
b3c11ac2 | 140 | snprintf(buf->str, sizeof(buf->str), |
ae4df11a LP |
141 | "%c%c%c%c %s-endian (0x%08x)", |
142 | printable_char(format & 0xff), | |
143 | printable_char((format >> 8) & 0xff), | |
144 | printable_char((format >> 16) & 0xff), | |
145 | printable_char((format >> 24) & 0x7f), | |
146 | format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little", | |
147 | format); | |
148 | ||
b3c11ac2 | 149 | return buf->str; |
ae4df11a LP |
150 | } |
151 | EXPORT_SYMBOL(drm_get_format_name); | |
152 | ||
333d2da5 LP |
153 | /* |
154 | * Internal function to query information for a given format. See | |
155 | * drm_format_info() for the public API. | |
84770cc2 | 156 | */ |
333d2da5 | 157 | const struct drm_format_info *__drm_format_info(u32 format) |
84770cc2 LP |
158 | { |
159 | static const struct drm_format_info formats[] = { | |
160 | { .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
161 | { .format = DRM_FORMAT_RGB332, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
162 | { .format = DRM_FORMAT_BGR233, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
163 | { .format = DRM_FORMAT_XRGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
164 | { .format = DRM_FORMAT_XBGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
165 | { .format = DRM_FORMAT_RGBX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
166 | { .format = DRM_FORMAT_BGRX4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
4cc4e1b4 MR |
167 | { .format = DRM_FORMAT_ARGB4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
168 | { .format = DRM_FORMAT_ABGR4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
169 | { .format = DRM_FORMAT_RGBA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
170 | { .format = DRM_FORMAT_BGRA4444, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
84770cc2 LP |
171 | { .format = DRM_FORMAT_XRGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
172 | { .format = DRM_FORMAT_XBGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
173 | { .format = DRM_FORMAT_RGBX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
174 | { .format = DRM_FORMAT_BGRX5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
4cc4e1b4 MR |
175 | { .format = DRM_FORMAT_ARGB1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
176 | { .format = DRM_FORMAT_ABGR1555, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
177 | { .format = DRM_FORMAT_RGBA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
178 | { .format = DRM_FORMAT_BGRA5551, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
84770cc2 LP |
179 | { .format = DRM_FORMAT_RGB565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, |
180 | { .format = DRM_FORMAT_BGR565, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
181 | { .format = DRM_FORMAT_RGB888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
182 | { .format = DRM_FORMAT_BGR888, .depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
183 | { .format = DRM_FORMAT_XRGB8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
184 | { .format = DRM_FORMAT_XBGR8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
185 | { .format = DRM_FORMAT_RGBX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
186 | { .format = DRM_FORMAT_BGRX8888, .depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
4cc4e1b4 MR |
187 | { .format = DRM_FORMAT_RGB565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
188 | { .format = DRM_FORMAT_BGR565_A8, .depth = 24, .num_planes = 2, .cpp = { 2, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
84770cc2 LP |
189 | { .format = DRM_FORMAT_XRGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, |
190 | { .format = DRM_FORMAT_XBGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
191 | { .format = DRM_FORMAT_RGBX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
192 | { .format = DRM_FORMAT_BGRX1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
4cc4e1b4 MR |
193 | { .format = DRM_FORMAT_ARGB2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
194 | { .format = DRM_FORMAT_ABGR2101010, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
195 | { .format = DRM_FORMAT_RGBA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
196 | { .format = DRM_FORMAT_BGRA1010102, .depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
197 | { .format = DRM_FORMAT_ARGB8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
198 | { .format = DRM_FORMAT_ABGR8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
199 | { .format = DRM_FORMAT_RGBA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
200 | { .format = DRM_FORMAT_BGRA8888, .depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
88ab9c76 KS |
201 | { .format = DRM_FORMAT_XRGB16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 }, |
202 | { .format = DRM_FORMAT_XBGR16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1 }, | |
203 | { .format = DRM_FORMAT_ARGB16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
204 | { .format = DRM_FORMAT_ABGR16161616F, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
4cc4e1b4 MR |
205 | { .format = DRM_FORMAT_RGB888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, |
206 | { .format = DRM_FORMAT_BGR888_A8, .depth = 32, .num_planes = 2, .cpp = { 3, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
207 | { .format = DRM_FORMAT_XRGB8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
208 | { .format = DRM_FORMAT_XBGR8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
209 | { .format = DRM_FORMAT_RGBX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
210 | { .format = DRM_FORMAT_BGRX8888_A8, .depth = 32, .num_planes = 2, .cpp = { 4, 1, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true }, | |
ce2d5461 AKH |
211 | { .format = DRM_FORMAT_YUV410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true }, |
212 | { .format = DRM_FORMAT_YVU410, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4, .is_yuv = true }, | |
213 | { .format = DRM_FORMAT_YUV411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true }, | |
214 | { .format = DRM_FORMAT_YVU411, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1, .is_yuv = true }, | |
215 | { .format = DRM_FORMAT_YUV420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true }, | |
216 | { .format = DRM_FORMAT_YVU420, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2, .is_yuv = true }, | |
217 | { .format = DRM_FORMAT_YUV422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true }, | |
218 | { .format = DRM_FORMAT_YVU422, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1, .is_yuv = true }, | |
219 | { .format = DRM_FORMAT_YUV444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true }, | |
220 | { .format = DRM_FORMAT_YVU444, .depth = 0, .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1, .is_yuv = true }, | |
221 | { .format = DRM_FORMAT_NV12, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true }, | |
222 | { .format = DRM_FORMAT_NV21, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2, .is_yuv = true }, | |
223 | { .format = DRM_FORMAT_NV16, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, | |
224 | { .format = DRM_FORMAT_NV61, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, | |
225 | { .format = DRM_FORMAT_NV24, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, | |
226 | { .format = DRM_FORMAT_NV42, .depth = 0, .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, | |
227 | { .format = DRM_FORMAT_YUYV, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, | |
228 | { .format = DRM_FORMAT_YVYU, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, | |
229 | { .format = DRM_FORMAT_UYVY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, | |
230 | { .format = DRM_FORMAT_VYUY, .depth = 0, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, | |
61e49394 | 231 | { .format = DRM_FORMAT_XYUV8888, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, |
7ba0fee2 | 232 | { .format = DRM_FORMAT_VUY888, .depth = 0, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, |
ce2d5461 | 233 | { .format = DRM_FORMAT_AYUV, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, |
50bf5d7d SS |
234 | { .format = DRM_FORMAT_Y210, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, |
235 | { .format = DRM_FORMAT_Y212, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, | |
236 | { .format = DRM_FORMAT_Y216, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true }, | |
ff01e697 ML |
237 | { .format = DRM_FORMAT_Y410, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, |
238 | { .format = DRM_FORMAT_Y412, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, | |
239 | { .format = DRM_FORMAT_Y416, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true, .is_yuv = true }, | |
240 | { .format = DRM_FORMAT_XVYU2101010, .depth = 0, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, | |
241 | { .format = DRM_FORMAT_XVYU12_16161616, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, | |
242 | { .format = DRM_FORMAT_XVYU16161616, .depth = 0, .num_planes = 1, .cpp = { 8, 0, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true }, | |
697b6b85 AG |
243 | { .format = DRM_FORMAT_Y0L0, .depth = 0, .num_planes = 1, |
244 | .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 }, | |
245 | .hsub = 2, .vsub = 2, .has_alpha = true, .is_yuv = true }, | |
246 | { .format = DRM_FORMAT_X0L0, .depth = 0, .num_planes = 1, | |
247 | .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 }, | |
248 | .hsub = 2, .vsub = 2, .is_yuv = true }, | |
249 | { .format = DRM_FORMAT_Y0L2, .depth = 0, .num_planes = 1, | |
250 | .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 }, | |
251 | .hsub = 2, .vsub = 2, .has_alpha = true, .is_yuv = true }, | |
252 | { .format = DRM_FORMAT_X0L2, .depth = 0, .num_planes = 1, | |
253 | .char_per_block = { 8, 0, 0 }, .block_w = { 2, 0, 0 }, .block_h = { 2, 0, 0 }, | |
254 | .hsub = 2, .vsub = 2, .is_yuv = true }, | |
05f8bc82 | 255 | { .format = DRM_FORMAT_P010, .depth = 0, .num_planes = 2, |
836b131d | 256 | .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, |
05f8bc82 RL |
257 | .hsub = 2, .vsub = 2, .is_yuv = true}, |
258 | { .format = DRM_FORMAT_P012, .depth = 0, .num_planes = 2, | |
836b131d | 259 | .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, |
05f8bc82 RL |
260 | .hsub = 2, .vsub = 2, .is_yuv = true}, |
261 | { .format = DRM_FORMAT_P016, .depth = 0, .num_planes = 2, | |
836b131d | 262 | .char_per_block = { 2, 4, 0 }, .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, |
05f8bc82 | 263 | .hsub = 2, .vsub = 2, .is_yuv = true}, |
7ba0fee2 BS |
264 | { .format = DRM_FORMAT_P210, .depth = 0, |
265 | .num_planes = 2, .char_per_block = { 2, 4, 0 }, | |
96227287 | 266 | .block_w = { 1, 1, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2, |
7ba0fee2 BS |
267 | .vsub = 1, .is_yuv = true }, |
268 | { .format = DRM_FORMAT_VUY101010, .depth = 0, | |
269 | .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 1, .vsub = 1, | |
270 | .is_yuv = true }, | |
271 | { .format = DRM_FORMAT_YUV420_8BIT, .depth = 0, | |
272 | .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2, | |
273 | .is_yuv = true }, | |
274 | { .format = DRM_FORMAT_YUV420_10BIT, .depth = 0, | |
275 | .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2, | |
276 | .is_yuv = true }, | |
84770cc2 LP |
277 | }; |
278 | ||
279 | unsigned int i; | |
280 | ||
281 | for (i = 0; i < ARRAY_SIZE(formats); ++i) { | |
282 | if (formats[i].format == format) | |
283 | return &formats[i]; | |
284 | } | |
285 | ||
286 | return NULL; | |
287 | } | |
333d2da5 LP |
288 | |
289 | /** | |
290 | * drm_format_info - query information for a given format | |
291 | * @format: pixel format (DRM_FORMAT_*) | |
292 | * | |
293 | * The caller should only pass a supported pixel format to this function. | |
294 | * Unsupported pixel formats will generate a warning in the kernel log. | |
295 | * | |
296 | * Returns: | |
297 | * The instance of struct drm_format_info that describes the pixel format, or | |
298 | * NULL if the format is unsupported. | |
299 | */ | |
300 | const struct drm_format_info *drm_format_info(u32 format) | |
301 | { | |
302 | const struct drm_format_info *info; | |
303 | ||
304 | info = __drm_format_info(format); | |
305 | WARN_ON(!info); | |
306 | return info; | |
307 | } | |
84770cc2 LP |
308 | EXPORT_SYMBOL(drm_format_info); |
309 | ||
6a0f9ebf VS |
310 | /** |
311 | * drm_get_format_info - query information for a given framebuffer configuration | |
312 | * @dev: DRM device | |
313 | * @mode_cmd: metadata from the userspace fb creation request | |
314 | * | |
315 | * Returns: | |
316 | * The instance of struct drm_format_info that describes the pixel format, or | |
317 | * NULL if the format is unsupported. | |
318 | */ | |
319 | const struct drm_format_info * | |
320 | drm_get_format_info(struct drm_device *dev, | |
321 | const struct drm_mode_fb_cmd2 *mode_cmd) | |
322 | { | |
323 | const struct drm_format_info *info = NULL; | |
324 | ||
325 | if (dev->mode_config.funcs->get_format_info) | |
326 | info = dev->mode_config.funcs->get_format_info(mode_cmd); | |
327 | ||
328 | if (!info) | |
329 | info = drm_format_info(mode_cmd->pixel_format); | |
330 | ||
331 | return info; | |
332 | } | |
333 | EXPORT_SYMBOL(drm_get_format_info); | |
334 | ||
042bf753 AG |
335 | /** |
336 | * drm_format_info_block_width - width in pixels of block. | |
337 | * @info: pixel format info | |
338 | * @plane: plane index | |
339 | * | |
340 | * Returns: | |
341 | * The width in pixels of a block, depending on the plane index. | |
342 | */ | |
343 | unsigned int drm_format_info_block_width(const struct drm_format_info *info, | |
344 | int plane) | |
345 | { | |
346 | if (!info || plane < 0 || plane >= info->num_planes) | |
347 | return 0; | |
348 | ||
349 | if (!info->block_w[plane]) | |
350 | return 1; | |
351 | return info->block_w[plane]; | |
352 | } | |
353 | EXPORT_SYMBOL(drm_format_info_block_width); | |
354 | ||
355 | /** | |
356 | * drm_format_info_block_height - height in pixels of a block | |
357 | * @info: pixel format info | |
358 | * @plane: plane index | |
359 | * | |
360 | * Returns: | |
361 | * The height in pixels of a block, depending on the plane index. | |
362 | */ | |
363 | unsigned int drm_format_info_block_height(const struct drm_format_info *info, | |
364 | int plane) | |
365 | { | |
366 | if (!info || plane < 0 || plane >= info->num_planes) | |
367 | return 0; | |
368 | ||
369 | if (!info->block_h[plane]) | |
370 | return 1; | |
371 | return info->block_h[plane]; | |
372 | } | |
373 | EXPORT_SYMBOL(drm_format_info_block_height); | |
374 | ||
375 | /** | |
376 | * drm_format_info_min_pitch - computes the minimum required pitch in bytes | |
377 | * @info: pixel format info | |
378 | * @plane: plane index | |
379 | * @buffer_width: buffer width in pixels | |
380 | * | |
381 | * Returns: | |
382 | * The minimum required pitch in bytes for a buffer by taking into consideration | |
383 | * the pixel format information and the buffer width. | |
384 | */ | |
385 | uint64_t drm_format_info_min_pitch(const struct drm_format_info *info, | |
386 | int plane, unsigned int buffer_width) | |
387 | { | |
388 | if (!info || plane < 0 || plane >= info->num_planes) | |
389 | return 0; | |
390 | ||
391 | return DIV_ROUND_UP_ULL((u64)buffer_width * info->char_per_block[plane], | |
392 | drm_format_info_block_width(info, plane) * | |
393 | drm_format_info_block_height(info, plane)); | |
394 | } | |
395 | EXPORT_SYMBOL(drm_format_info_min_pitch); |