Merge branches 'acpi-scan', 'acpi-pnp' and 'acpi-sleep'
[linux-2.6-microblaze.git] / drivers / gpu / drm / selftests / test-drm_framebuffer.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Test cases for the drm_framebuffer functions
4  */
5
6 #include <linux/kernel.h>
7
8 #include <drm/drm_device.h>
9 #include <drm/drm_mode.h>
10 #include <drm/drm_fourcc.h>
11
12 #include "../drm_crtc_internal.h"
13
14 #include "test-drm_modeset_common.h"
15
16 #define MIN_WIDTH 4
17 #define MAX_WIDTH 4096
18 #define MIN_HEIGHT 4
19 #define MAX_HEIGHT 4096
20
21 struct drm_framebuffer_test {
22         int buffer_created;
23         struct drm_mode_fb_cmd2 cmd;
24         const char *name;
25 };
26
27 static struct drm_framebuffer_test createbuffer_tests[] = {
28 { .buffer_created = 1, .name = "ABGR8888 normal sizes",
29         .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_ABGR8888,
30                  .handles = { 1, 0, 0 }, .pitches = { 4 * 600, 0, 0 },
31         }
32 },
33 { .buffer_created = 1, .name = "ABGR8888 max sizes",
34         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
35                  .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
36         }
37 },
38 { .buffer_created = 1, .name = "ABGR8888 pitch greater than min required",
39         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
40                  .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH + 1, 0, 0 },
41         }
42 },
43 { .buffer_created = 0, .name = "ABGR8888 pitch less than min required",
44         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
45                  .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH - 1, 0, 0 },
46         }
47 },
48 { .buffer_created = 0, .name = "ABGR8888 Invalid width",
49         .cmd = { .width = MAX_WIDTH + 1, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
50                  .handles = { 1, 0, 0 }, .pitches = { 4 * (MAX_WIDTH + 1), 0, 0 },
51         }
52 },
53 { .buffer_created = 0, .name = "ABGR8888 Invalid buffer handle",
54         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
55                  .handles = { 0, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
56         }
57 },
58 { .buffer_created = 0, .name = "No pixel format",
59         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = 0,
60                  .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
61         }
62 },
63 { .buffer_created = 0, .name = "ABGR8888 Width 0",
64         .cmd = { .width = 0, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
65                  .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
66         }
67 },
68 { .buffer_created = 0, .name = "ABGR8888 Height 0",
69         .cmd = { .width = MAX_WIDTH, .height = 0, .pixel_format = DRM_FORMAT_ABGR8888,
70                  .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
71         }
72 },
73 { .buffer_created = 0, .name = "ABGR8888 Out of bound height * pitch combination",
74         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
75                  .handles = { 1, 0, 0 }, .offsets = { UINT_MAX - 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
76         }
77 },
78 { .buffer_created = 1, .name = "ABGR8888 Large buffer offset",
79         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
80                  .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
81         }
82 },
83 { .buffer_created = 1, .name = "ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers",
84         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
85                  .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
86                  .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
87         }
88 },
89 { .buffer_created = 1, .name = "ABGR8888 Valid buffer modifier",
90         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
91                  .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
92                  .flags = DRM_MODE_FB_MODIFIERS, .modifier = { AFBC_FORMAT_MOD_YTR, 0, 0 },
93         }
94 },
95 { .buffer_created = 0, .name = "ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)",
96         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
97                  .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
98                  .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
99                  .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
100         }
101 },
102 { .buffer_created = 1, .name = "ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS",
103         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
104                  .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
105                  .pitches = { 4 * MAX_WIDTH, 4 * MAX_WIDTH, 0 },
106         }
107 },
108 { .buffer_created = 0, .name = "ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS",
109         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
110                  .handles = { 1, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
111                  .pitches = { 4 * MAX_WIDTH, 4 * MAX_WIDTH, 0 },
112         }
113 },
114 { .buffer_created = 1, .name = "NV12 Normal sizes",
115         .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_NV12,
116                  .handles = { 1, 1, 0 }, .pitches = { 600, 600, 0 },
117         }
118 },
119 { .buffer_created = 1, .name = "NV12 Max sizes",
120         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
121                  .handles = { 1, 1, 0 }, .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
122         }
123 },
124 { .buffer_created = 0, .name = "NV12 Invalid pitch",
125         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
126                  .handles = { 1, 1, 0 }, .pitches = { MAX_WIDTH, MAX_WIDTH - 1, 0 },
127         }
128 },
129 { .buffer_created = 0, .name = "NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag",
130         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
131                  .handles = { 1, 1, 0 }, .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
132                  .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
133         }
134 },
135 { .buffer_created = 0, .name = "NV12 different  modifier per-plane",
136         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
137                  .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
138                  .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
139                  .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
140         }
141 },
142 { .buffer_created = 1, .name = "NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE",
143         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
144                  .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
145                  .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0 },
146                  .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
147         }
148 },
149 { .buffer_created = 0, .name = "NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS",
150         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
151                  .handles = { 1, 1, 0 }, .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE,
152                                                        DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0 },
153                  .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
154         }
155 },
156 { .buffer_created = 0, .name = "NV12 Modifier for inexistent plane",
157         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
158                  .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
159                  .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, DRM_FORMAT_MOD_SAMSUNG_64_32_TILE,
160                                DRM_FORMAT_MOD_SAMSUNG_64_32_TILE },
161                  .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
162         }
163 },
164 { .buffer_created = 0, .name = "NV12 Handle for inexistent plane",
165         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
166                  .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
167         }
168 },
169 { .buffer_created = 1, .name = "NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS",
170         .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_NV12,
171                  .handles = { 1, 1, 1 }, .pitches = { 600, 600, 600 },
172         }
173 },
174 { .buffer_created = 1, .name = "YVU420 Normal sizes",
175         .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_YVU420,
176                  .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
177                  .pitches = { 600, 300, 300 },
178         }
179 },
180 { .buffer_created = 1, .name = "YVU420 DRM_MODE_FB_MODIFIERS set without modifier",
181         .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_YVU420,
182                  .handles = { 1, 1, 1 }, .pitches = { 600, 300, 300 },
183         }
184 },
185 { .buffer_created = 1, .name = "YVU420 Max sizes",
186         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
187                  .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2),
188                                                       DIV_ROUND_UP(MAX_WIDTH, 2) },
189         }
190 },
191 { .buffer_created = 0, .name = "YVU420 Invalid pitch",
192         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
193                  .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) - 1,
194                                                       DIV_ROUND_UP(MAX_WIDTH, 2) },
195         }
196 },
197 { .buffer_created = 1, .name = "YVU420 Different pitches",
198         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
199                  .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) + 1,
200                                                       DIV_ROUND_UP(MAX_WIDTH, 2) + 7 },
201         }
202 },
203 { .buffer_created = 1, .name = "YVU420 Different buffer offsets/pitches",
204         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
205                  .handles = { 1, 1, 1 }, .offsets = { MAX_WIDTH, MAX_WIDTH  + MAX_WIDTH * MAX_HEIGHT,
206                                                       MAX_WIDTH  + 2 * MAX_WIDTH * MAX_HEIGHT },
207                  .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) + 1, DIV_ROUND_UP(MAX_WIDTH, 2) + 7 },
208         }
209 },
210 { .buffer_created = 0, .name = "YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS",
211         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
212                  .handles = { 1, 1, 1 }, .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 },
213                  .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
214         }
215 },
216 { .buffer_created = 0, .name = "YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS",
217         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
218                  .handles = { 1, 1, 1 }, .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 },
219                  .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
220         }
221 },
222 { .buffer_created = 0, .name = "YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS",
223         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
224                  .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
225                  .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 },
226                  .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
227         }
228 },
229 { .buffer_created = 1, .name = "YVU420 Valid modifier",
230         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
231                  .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
232                  .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE },
233                  .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
234         }
235 },
236 { .buffer_created = 0, .name = "YVU420 Different modifiers per plane",
237         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
238                  .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
239                  .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_YTR,
240                                AFBC_FORMAT_MOD_SPARSE },
241                  .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
242         }
243 },
244 { .buffer_created = 0, .name = "YVU420 Modifier for inexistent plane",
245         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
246                  .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
247                  .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE,
248                                AFBC_FORMAT_MOD_SPARSE },
249                  .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
250         }
251 },
252 { .buffer_created = 1, .name = "X0L2 Normal sizes",
253         .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_X0L2,
254                  .handles = { 1, 0, 0 }, .pitches = { 1200, 0, 0 }
255         }
256 },
257 { .buffer_created = 1, .name = "X0L2 Max sizes",
258         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
259                  .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH, 0, 0 }
260         }
261 },
262 { .buffer_created = 0, .name = "X0L2 Invalid pitch",
263         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
264                  .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH - 1, 0, 0 }
265         }
266 },
267 { .buffer_created = 1, .name = "X0L2 Pitch greater than minimum required",
268         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
269                  .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }
270         }
271 },
272 { .buffer_created = 0, .name = "X0L2 Handle for inexistent plane",
273         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
274                  .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
275                  .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }
276         }
277 },
278 { .buffer_created = 1, .name = "X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set",
279         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
280                  .handles = { 1, 0, 0 }, .offsets = { 0, 0, 3 },
281                  .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }
282         }
283 },
284 { .buffer_created = 0, .name = "X0L2 Modifier without DRM_MODE_FB_MODIFIERS set",
285         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
286                  .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 },
287                  .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 },
288         }
289 },
290 { .buffer_created = 1, .name = "X0L2 Valid modifier",
291         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
292                  .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 },
293                  .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
294         }
295 },
296 { .buffer_created = 0, .name = "X0L2 Modifier for inexistent plane",
297         .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT,
298                  .pixel_format = DRM_FORMAT_X0L2, .handles = { 1, 0, 0 },
299                  .pitches = { 2 * MAX_WIDTH + 1, 0, 0 },
300                  .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 },
301                  .flags = DRM_MODE_FB_MODIFIERS,
302         }
303 },
304 };
305
306 static struct drm_framebuffer *fb_create_mock(struct drm_device *dev,
307                                               struct drm_file *file_priv,
308                                               const struct drm_mode_fb_cmd2 *mode_cmd)
309 {
310         int *buffer_created = dev->dev_private;
311         *buffer_created = 1;
312         return ERR_PTR(-EINVAL);
313 }
314
315 static struct drm_mode_config_funcs mock_config_funcs = {
316         .fb_create = fb_create_mock,
317 };
318
319 static struct drm_device mock_drm_device = {
320         .mode_config = {
321                 .min_width = MIN_WIDTH,
322                 .max_width = MAX_WIDTH,
323                 .min_height = MIN_HEIGHT,
324                 .max_height = MAX_HEIGHT,
325                 .allow_fb_modifiers = true,
326                 .funcs = &mock_config_funcs,
327         },
328 };
329
330 static int execute_drm_mode_fb_cmd2(struct drm_mode_fb_cmd2 *r)
331 {
332         int buffer_created = 0;
333
334         mock_drm_device.dev_private = &buffer_created;
335         drm_internal_framebuffer_create(&mock_drm_device, r, NULL);
336         return buffer_created;
337 }
338
339 int igt_check_drm_framebuffer_create(void *ignored)
340 {
341         int i = 0;
342
343         for (i = 0; i < ARRAY_SIZE(createbuffer_tests); i++) {
344                 FAIL(createbuffer_tests[i].buffer_created !=
345                                 execute_drm_mode_fb_cmd2(&createbuffer_tests[i].cmd),
346                      "Test %d: \"%s\" failed\n", i, createbuffer_tests[i].name);
347         }
348
349         return 0;
350 }