drm: remove `const` attribute to hint at caller that they now own the memory
[cascardo/linux.git] / drivers / gpu / drm / drm_fourcc.c
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/drmP.h>
31 #include <drm/drm_fourcc.h>
32
33 static char printable_char(int c)
34 {
35         return isascii(c) && isprint(c) ? c : '?';
36 }
37
38 /**
39  * drm_get_format_name - return a string for drm fourcc format
40  * @format: format to compute name of
41  *
42  * Note that the buffer returned by this function is owned by the caller
43  * and will need to be freed using kfree().
44  */
45 char *drm_get_format_name(uint32_t format)
46 {
47         char *buf = kmalloc(32, GFP_KERNEL);
48
49         snprintf(buf, 32,
50                  "%c%c%c%c %s-endian (0x%08x)",
51                  printable_char(format & 0xff),
52                  printable_char((format >> 8) & 0xff),
53                  printable_char((format >> 16) & 0xff),
54                  printable_char((format >> 24) & 0x7f),
55                  format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
56                  format);
57
58         return buf;
59 }
60 EXPORT_SYMBOL(drm_get_format_name);
61
62 /**
63  * drm_fb_get_bpp_depth - get the bpp/depth values for format
64  * @format: pixel format (DRM_FORMAT_*)
65  * @depth: storage for the depth value
66  * @bpp: storage for the bpp value
67  *
68  * This only supports RGB formats here for compat with code that doesn't use
69  * pixel formats directly yet.
70  */
71 void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
72                           int *bpp)
73 {
74         char *format_name;
75
76         switch (format) {
77         case DRM_FORMAT_C8:
78         case DRM_FORMAT_RGB332:
79         case DRM_FORMAT_BGR233:
80                 *depth = 8;
81                 *bpp = 8;
82                 break;
83         case DRM_FORMAT_XRGB1555:
84         case DRM_FORMAT_XBGR1555:
85         case DRM_FORMAT_RGBX5551:
86         case DRM_FORMAT_BGRX5551:
87         case DRM_FORMAT_ARGB1555:
88         case DRM_FORMAT_ABGR1555:
89         case DRM_FORMAT_RGBA5551:
90         case DRM_FORMAT_BGRA5551:
91                 *depth = 15;
92                 *bpp = 16;
93                 break;
94         case DRM_FORMAT_RGB565:
95         case DRM_FORMAT_BGR565:
96                 *depth = 16;
97                 *bpp = 16;
98                 break;
99         case DRM_FORMAT_RGB888:
100         case DRM_FORMAT_BGR888:
101                 *depth = 24;
102                 *bpp = 24;
103                 break;
104         case DRM_FORMAT_XRGB8888:
105         case DRM_FORMAT_XBGR8888:
106         case DRM_FORMAT_RGBX8888:
107         case DRM_FORMAT_BGRX8888:
108                 *depth = 24;
109                 *bpp = 32;
110                 break;
111         case DRM_FORMAT_XRGB2101010:
112         case DRM_FORMAT_XBGR2101010:
113         case DRM_FORMAT_RGBX1010102:
114         case DRM_FORMAT_BGRX1010102:
115         case DRM_FORMAT_ARGB2101010:
116         case DRM_FORMAT_ABGR2101010:
117         case DRM_FORMAT_RGBA1010102:
118         case DRM_FORMAT_BGRA1010102:
119                 *depth = 30;
120                 *bpp = 32;
121                 break;
122         case DRM_FORMAT_ARGB8888:
123         case DRM_FORMAT_ABGR8888:
124         case DRM_FORMAT_RGBA8888:
125         case DRM_FORMAT_BGRA8888:
126                 *depth = 32;
127                 *bpp = 32;
128                 break;
129         default:
130                 format_name = drm_get_format_name(format);
131                 DRM_DEBUG_KMS("unsupported pixel format %s\n", format_name);
132                 kfree(format_name);
133                 *depth = 0;
134                 *bpp = 0;
135                 break;
136         }
137 }
138 EXPORT_SYMBOL(drm_fb_get_bpp_depth);
139
140 /**
141  * drm_format_num_planes - get the number of planes for format
142  * @format: pixel format (DRM_FORMAT_*)
143  *
144  * Returns:
145  * The number of planes used by the specified pixel format.
146  */
147 int drm_format_num_planes(uint32_t format)
148 {
149         switch (format) {
150         case DRM_FORMAT_YUV410:
151         case DRM_FORMAT_YVU410:
152         case DRM_FORMAT_YUV411:
153         case DRM_FORMAT_YVU411:
154         case DRM_FORMAT_YUV420:
155         case DRM_FORMAT_YVU420:
156         case DRM_FORMAT_YUV422:
157         case DRM_FORMAT_YVU422:
158         case DRM_FORMAT_YUV444:
159         case DRM_FORMAT_YVU444:
160                 return 3;
161         case DRM_FORMAT_NV12:
162         case DRM_FORMAT_NV21:
163         case DRM_FORMAT_NV16:
164         case DRM_FORMAT_NV61:
165         case DRM_FORMAT_NV24:
166         case DRM_FORMAT_NV42:
167                 return 2;
168         default:
169                 return 1;
170         }
171 }
172 EXPORT_SYMBOL(drm_format_num_planes);
173
174 /**
175  * drm_format_plane_cpp - determine the bytes per pixel value
176  * @format: pixel format (DRM_FORMAT_*)
177  * @plane: plane index
178  *
179  * Returns:
180  * The bytes per pixel value for the specified plane.
181  */
182 int drm_format_plane_cpp(uint32_t format, int plane)
183 {
184         unsigned int depth;
185         int bpp;
186
187         if (plane >= drm_format_num_planes(format))
188                 return 0;
189
190         switch (format) {
191         case DRM_FORMAT_YUYV:
192         case DRM_FORMAT_YVYU:
193         case DRM_FORMAT_UYVY:
194         case DRM_FORMAT_VYUY:
195                 return 2;
196         case DRM_FORMAT_NV12:
197         case DRM_FORMAT_NV21:
198         case DRM_FORMAT_NV16:
199         case DRM_FORMAT_NV61:
200         case DRM_FORMAT_NV24:
201         case DRM_FORMAT_NV42:
202                 return plane ? 2 : 1;
203         case DRM_FORMAT_YUV410:
204         case DRM_FORMAT_YVU410:
205         case DRM_FORMAT_YUV411:
206         case DRM_FORMAT_YVU411:
207         case DRM_FORMAT_YUV420:
208         case DRM_FORMAT_YVU420:
209         case DRM_FORMAT_YUV422:
210         case DRM_FORMAT_YVU422:
211         case DRM_FORMAT_YUV444:
212         case DRM_FORMAT_YVU444:
213                 return 1;
214         default:
215                 drm_fb_get_bpp_depth(format, &depth, &bpp);
216                 return bpp >> 3;
217         }
218 }
219 EXPORT_SYMBOL(drm_format_plane_cpp);
220
221 /**
222  * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
223  * @format: pixel format (DRM_FORMAT_*)
224  *
225  * Returns:
226  * The horizontal chroma subsampling factor for the
227  * specified pixel format.
228  */
229 int drm_format_horz_chroma_subsampling(uint32_t format)
230 {
231         switch (format) {
232         case DRM_FORMAT_YUV411:
233         case DRM_FORMAT_YVU411:
234         case DRM_FORMAT_YUV410:
235         case DRM_FORMAT_YVU410:
236                 return 4;
237         case DRM_FORMAT_YUYV:
238         case DRM_FORMAT_YVYU:
239         case DRM_FORMAT_UYVY:
240         case DRM_FORMAT_VYUY:
241         case DRM_FORMAT_NV12:
242         case DRM_FORMAT_NV21:
243         case DRM_FORMAT_NV16:
244         case DRM_FORMAT_NV61:
245         case DRM_FORMAT_YUV422:
246         case DRM_FORMAT_YVU422:
247         case DRM_FORMAT_YUV420:
248         case DRM_FORMAT_YVU420:
249                 return 2;
250         default:
251                 return 1;
252         }
253 }
254 EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
255
256 /**
257  * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
258  * @format: pixel format (DRM_FORMAT_*)
259  *
260  * Returns:
261  * The vertical chroma subsampling factor for the
262  * specified pixel format.
263  */
264 int drm_format_vert_chroma_subsampling(uint32_t format)
265 {
266         switch (format) {
267         case DRM_FORMAT_YUV410:
268         case DRM_FORMAT_YVU410:
269                 return 4;
270         case DRM_FORMAT_YUV420:
271         case DRM_FORMAT_YVU420:
272         case DRM_FORMAT_NV12:
273         case DRM_FORMAT_NV21:
274                 return 2;
275         default:
276                 return 1;
277         }
278 }
279 EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
280
281 /**
282  * drm_format_plane_width - width of the plane given the first plane
283  * @width: width of the first plane
284  * @format: pixel format
285  * @plane: plane index
286  *
287  * Returns:
288  * The width of @plane, given that the width of the first plane is @width.
289  */
290 int drm_format_plane_width(int width, uint32_t format, int plane)
291 {
292         if (plane >= drm_format_num_planes(format))
293                 return 0;
294
295         if (plane == 0)
296                 return width;
297
298         return width / drm_format_horz_chroma_subsampling(format);
299 }
300 EXPORT_SYMBOL(drm_format_plane_width);
301
302 /**
303  * drm_format_plane_height - height of the plane given the first plane
304  * @height: height of the first plane
305  * @format: pixel format
306  * @plane: plane index
307  *
308  * Returns:
309  * The height of @plane, given that the height of the first plane is @height.
310  */
311 int drm_format_plane_height(int height, uint32_t format, int plane)
312 {
313         if (plane >= drm_format_num_planes(format))
314                 return 0;
315
316         if (plane == 0)
317                 return height;
318
319         return height / drm_format_vert_chroma_subsampling(format);
320 }
321 EXPORT_SYMBOL(drm_format_plane_height);