xref: /linux/drivers/gpu/drm/tests/drm_format_helper_test.c (revision fb0a84e6de1b6bee0a0649cc7ed768f9ff2496bb)
1 // SPDX-License-Identifier: GPL-2.0+
2 
3 #include <kunit/test.h>
4 
5 #include <drm/drm_device.h>
6 #include <drm/drm_drv.h>
7 #include <drm/drm_file.h>
8 #include <drm/drm_format_helper.h>
9 #include <drm/drm_fourcc.h>
10 #include <drm/drm_framebuffer.h>
11 #include <drm/drm_gem_framebuffer_helper.h>
12 #include <drm/drm_kunit_helpers.h>
13 #include <drm/drm_mode.h>
14 #include <drm/drm_print.h>
15 #include <drm/drm_rect.h>
16 
17 #include "../drm_crtc_internal.h"
18 
19 #define TEST_BUF_SIZE 50
20 
21 #define TEST_USE_DEFAULT_PITCH 0
22 
23 struct convert_to_gray8_result {
24 	unsigned int dst_pitch;
25 	const u8 expected[TEST_BUF_SIZE];
26 };
27 
28 struct convert_to_rgb332_result {
29 	unsigned int dst_pitch;
30 	const u8 expected[TEST_BUF_SIZE];
31 };
32 
33 struct convert_to_rgb565_result {
34 	unsigned int dst_pitch;
35 	const u16 expected[TEST_BUF_SIZE];
36 	const u16 expected_swab[TEST_BUF_SIZE];
37 };
38 
39 struct convert_to_xrgb1555_result {
40 	unsigned int dst_pitch;
41 	const u16 expected[TEST_BUF_SIZE];
42 };
43 
44 struct convert_to_argb1555_result {
45 	unsigned int dst_pitch;
46 	const u16 expected[TEST_BUF_SIZE];
47 };
48 
49 struct convert_to_rgba5551_result {
50 	unsigned int dst_pitch;
51 	const u16 expected[TEST_BUF_SIZE];
52 };
53 
54 struct convert_to_rgb888_result {
55 	unsigned int dst_pitch;
56 	const u8 expected[TEST_BUF_SIZE];
57 };
58 
59 struct convert_to_argb8888_result {
60 	unsigned int dst_pitch;
61 	const u32 expected[TEST_BUF_SIZE];
62 };
63 
64 struct convert_to_xrgb2101010_result {
65 	unsigned int dst_pitch;
66 	const u32 expected[TEST_BUF_SIZE];
67 };
68 
69 struct convert_to_argb2101010_result {
70 	unsigned int dst_pitch;
71 	const u32 expected[TEST_BUF_SIZE];
72 };
73 
74 struct convert_to_mono_result {
75 	unsigned int dst_pitch;
76 	const u8 expected[TEST_BUF_SIZE];
77 };
78 
79 struct fb_swab_result {
80 	unsigned int dst_pitch;
81 	const u32 expected[TEST_BUF_SIZE];
82 };
83 
84 struct convert_xrgb8888_case {
85 	const char *name;
86 	unsigned int pitch;
87 	struct drm_rect clip;
88 	const u32 xrgb8888[TEST_BUF_SIZE];
89 	struct convert_to_gray8_result gray8_result;
90 	struct convert_to_rgb332_result rgb332_result;
91 	struct convert_to_rgb565_result rgb565_result;
92 	struct convert_to_xrgb1555_result xrgb1555_result;
93 	struct convert_to_argb1555_result argb1555_result;
94 	struct convert_to_rgba5551_result rgba5551_result;
95 	struct convert_to_rgb888_result rgb888_result;
96 	struct convert_to_argb8888_result argb8888_result;
97 	struct convert_to_xrgb2101010_result xrgb2101010_result;
98 	struct convert_to_argb2101010_result argb2101010_result;
99 	struct convert_to_mono_result mono_result;
100 	struct fb_swab_result swab_result;
101 };
102 
103 static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
104 	{
105 		.name = "single_pixel_source_buffer",
106 		.pitch = 1 * 4,
107 		.clip = DRM_RECT_INIT(0, 0, 1, 1),
108 		.xrgb8888 = { 0x01FF0000 },
109 		.gray8_result = {
110 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
111 			.expected = { 0x4C },
112 		},
113 		.rgb332_result = {
114 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
115 			.expected = { 0xE0 },
116 		},
117 		.rgb565_result = {
118 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
119 			.expected = { 0xF800 },
120 			.expected_swab = { 0x00F8 },
121 		},
122 		.xrgb1555_result = {
123 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
124 			.expected = { 0x7C00 },
125 		},
126 		.argb1555_result = {
127 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
128 			.expected = { 0xFC00 },
129 		},
130 		.rgba5551_result = {
131 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
132 			.expected = { 0xF801 },
133 		},
134 		.rgb888_result = {
135 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
136 			.expected = { 0x00, 0x00, 0xFF },
137 		},
138 		.argb8888_result = {
139 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
140 			.expected = { 0xFFFF0000 },
141 		},
142 		.xrgb2101010_result = {
143 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
144 			.expected = { 0x3FF00000 },
145 		},
146 		.argb2101010_result = {
147 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
148 			.expected = { 0xFFF00000 },
149 		},
150 		.mono_result = {
151 			.dst_pitch =  TEST_USE_DEFAULT_PITCH,
152 			.expected = { 0b0 },
153 		},
154 		.swab_result = {
155 			.dst_pitch =  TEST_USE_DEFAULT_PITCH,
156 			.expected = { 0x0000FF01 },
157 		},
158 	},
159 	{
160 		.name = "single_pixel_clip_rectangle",
161 		.pitch = 2 * 4,
162 		.clip = DRM_RECT_INIT(1, 1, 1, 1),
163 		.xrgb8888 = {
164 			0x00000000, 0x00000000,
165 			0x00000000, 0x10FF0000,
166 		},
167 		.gray8_result = {
168 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
169 			.expected = { 0x4C },
170 		},
171 		.rgb332_result = {
172 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
173 			.expected = { 0xE0 },
174 		},
175 		.rgb565_result = {
176 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
177 			.expected = { 0xF800 },
178 			.expected_swab = { 0x00F8 },
179 		},
180 		.xrgb1555_result = {
181 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
182 			.expected = { 0x7C00 },
183 		},
184 		.argb1555_result = {
185 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
186 			.expected = { 0xFC00 },
187 		},
188 		.rgba5551_result = {
189 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
190 			.expected = { 0xF801 },
191 		},
192 		.rgb888_result = {
193 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
194 			.expected = { 0x00, 0x00, 0xFF },
195 		},
196 		.argb8888_result = {
197 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
198 			.expected = { 0xFFFF0000 },
199 		},
200 		.xrgb2101010_result = {
201 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
202 			.expected = { 0x3FF00000 },
203 		},
204 		.argb2101010_result = {
205 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
206 			.expected = { 0xFFF00000 },
207 		},
208 		.mono_result = {
209 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
210 			.expected = { 0b0 },
211 		},
212 		.swab_result = {
213 			.dst_pitch =  TEST_USE_DEFAULT_PITCH,
214 			.expected = { 0x0000FF10 },
215 		},
216 	},
217 	{
218 		/* Well known colors: White, black, red, green, blue, magenta,
219 		 * yellow and cyan. Different values for the X in XRGB8888 to
220 		 * make sure it is ignored. Partial clip area.
221 		 */
222 		.name = "well_known_colors",
223 		.pitch = 4 * 4,
224 		.clip = DRM_RECT_INIT(1, 1, 2, 4),
225 		.xrgb8888 = {
226 			0x00000000, 0x00000000, 0x00000000, 0x00000000,
227 			0x00000000, 0x11FFFFFF, 0x22000000, 0x00000000,
228 			0x00000000, 0x33FF0000, 0x4400FF00, 0x00000000,
229 			0x00000000, 0x550000FF, 0x66FF00FF, 0x00000000,
230 			0x00000000, 0x77FFFF00, 0x8800FFFF, 0x00000000,
231 		},
232 		.gray8_result = {
233 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
234 			.expected = {
235 				0xFF, 0x00,
236 				0x4C, 0x99,
237 				0x19, 0x66,
238 				0xE5, 0xB2,
239 			},
240 		},
241 		.rgb332_result = {
242 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
243 			.expected = {
244 				0xFF, 0x00,
245 				0xE0, 0x1C,
246 				0x03, 0xE3,
247 				0xFC, 0x1F,
248 			},
249 		},
250 		.rgb565_result = {
251 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
252 			.expected = {
253 				0xFFFF, 0x0000,
254 				0xF800, 0x07E0,
255 				0x001F, 0xF81F,
256 				0xFFE0, 0x07FF,
257 			},
258 			.expected_swab = {
259 				0xFFFF, 0x0000,
260 				0x00F8, 0xE007,
261 				0x1F00, 0x1FF8,
262 				0xE0FF, 0xFF07,
263 			},
264 		},
265 		.xrgb1555_result = {
266 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
267 			.expected = {
268 				0x7FFF, 0x0000,
269 				0x7C00, 0x03E0,
270 				0x001F, 0x7C1F,
271 				0x7FE0, 0x03FF,
272 			},
273 		},
274 		.argb1555_result = {
275 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
276 			.expected = {
277 				0xFFFF, 0x8000,
278 				0xFC00, 0x83E0,
279 				0x801F, 0xFC1F,
280 				0xFFE0, 0x83FF,
281 			},
282 		},
283 		.rgba5551_result = {
284 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
285 			.expected = {
286 				0xFFFF, 0x0001,
287 				0xF801, 0x07C1,
288 				0x003F, 0xF83F,
289 				0xFFC1, 0x07FF,
290 			},
291 		},
292 		.rgb888_result = {
293 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
294 			.expected = {
295 				0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
296 				0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,
297 				0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF,
298 				0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
299 			},
300 		},
301 		.argb8888_result = {
302 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
303 			.expected = {
304 				0xFFFFFFFF, 0xFF000000,
305 				0xFFFF0000, 0xFF00FF00,
306 				0xFF0000FF, 0xFFFF00FF,
307 				0xFFFFFF00, 0xFF00FFFF,
308 			},
309 		},
310 		.xrgb2101010_result = {
311 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
312 			.expected = {
313 				0x3FFFFFFF, 0x00000000,
314 				0x3FF00000, 0x000FFC00,
315 				0x000003FF, 0x3FF003FF,
316 				0x3FFFFC00, 0x000FFFFF,
317 			},
318 		},
319 		.argb2101010_result = {
320 			.dst_pitch = TEST_USE_DEFAULT_PITCH,
321 			.expected = {
322 				0xFFFFFFFF, 0xC0000000,
323 				0xFFF00000, 0xC00FFC00,
324 				0xC00003FF, 0xFFF003FF,
325 				0xFFFFFC00, 0xC00FFFFF,
326 			},
327 		},
328 		.mono_result = {
329 			.dst_pitch =  TEST_USE_DEFAULT_PITCH,
330 			.expected = {
331 				0b01,
332 				0b10,
333 				0b00,
334 				0b11,
335 			},
336 		},
337 		.swab_result = {
338 			.dst_pitch =  TEST_USE_DEFAULT_PITCH,
339 			.expected = {
340 				0xFFFFFF11, 0x00000022,
341 				0x0000FF33, 0x00FF0044,
342 				0xFF000055, 0xFF00FF66,
343 				0x00FFFF77, 0xFFFF0088,
344 			},
345 		},
346 	},
347 	{
348 		/* Randomly picked colors. Full buffer within the clip area. */
349 		.name = "destination_pitch",
350 		.pitch = 3 * 4,
351 		.clip = DRM_RECT_INIT(0, 0, 3, 3),
352 		.xrgb8888 = {
353 			0xA10E449C, 0xB1114D05, 0xC1A8F303,
354 			0xD16CF073, 0xA20E449C, 0xB2114D05,
355 			0xC2A80303, 0xD26CF073, 0xA30E449C,
356 		},
357 		.gray8_result = {
358 			.dst_pitch = 5,
359 			.expected = {
360 				0x3C, 0x33, 0xC4, 0x00, 0x00,
361 				0xBB, 0x3C, 0x33, 0x00, 0x00,
362 				0x34, 0xBB, 0x3C, 0x00, 0x00,
363 			},
364 		},
365 		.rgb332_result = {
366 			.dst_pitch = 5,
367 			.expected = {
368 				0x0A, 0x08, 0xBC, 0x00, 0x00,
369 				0x7D, 0x0A, 0x08, 0x00, 0x00,
370 				0xA0, 0x7D, 0x0A, 0x00, 0x00,
371 			},
372 		},
373 		.rgb565_result = {
374 			.dst_pitch = 10,
375 			.expected = {
376 				0x0A33, 0x1260, 0xAF80, 0x0000, 0x0000,
377 				0x6F8E, 0x0A33, 0x1260, 0x0000, 0x0000,
378 				0xA800, 0x6F8E, 0x0A33, 0x0000, 0x0000,
379 			},
380 			.expected_swab = {
381 				0x330A, 0x6012, 0x80AF, 0x0000, 0x0000,
382 				0x8E6F, 0x330A, 0x6012, 0x0000, 0x0000,
383 				0x00A8, 0x8E6F, 0x330A, 0x0000, 0x0000,
384 			},
385 		},
386 		.xrgb1555_result = {
387 			.dst_pitch = 10,
388 			.expected = {
389 				0x0513, 0x0920, 0x57C0, 0x0000, 0x0000,
390 				0x37CE, 0x0513, 0x0920, 0x0000, 0x0000,
391 				0x5400, 0x37CE, 0x0513, 0x0000, 0x0000,
392 			},
393 		},
394 		.argb1555_result = {
395 			.dst_pitch = 10,
396 			.expected = {
397 				0x8513, 0x8920, 0xD7C0, 0x0000, 0x0000,
398 				0xB7CE, 0x8513, 0x8920, 0x0000, 0x0000,
399 				0xD400, 0xB7CE, 0x8513, 0x0000, 0x0000,
400 			},
401 		},
402 		.rgba5551_result = {
403 			.dst_pitch = 10,
404 			.expected = {
405 				0x0A27, 0x1241, 0xAF81, 0x0000, 0x0000,
406 				0x6F9D, 0x0A27, 0x1241, 0x0000, 0x0000,
407 				0xA801, 0x6F9D, 0x0A27, 0x0000, 0x0000,
408 			},
409 		},
410 		.rgb888_result = {
411 			.dst_pitch = 15,
412 			.expected = {
413 				0x9C, 0x44, 0x0E, 0x05, 0x4D, 0x11, 0x03, 0xF3, 0xA8,
414 				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 				0x73, 0xF0, 0x6C, 0x9C, 0x44, 0x0E, 0x05, 0x4D, 0x11,
416 				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
417 				0x03, 0x03, 0xA8, 0x73, 0xF0, 0x6C, 0x9C, 0x44, 0x0E,
418 				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
419 			},
420 		},
421 		.argb8888_result = {
422 			.dst_pitch = 20,
423 			.expected = {
424 				0xFF0E449C, 0xFF114D05, 0xFFA8F303, 0x00000000, 0x00000000,
425 				0xFF6CF073, 0xFF0E449C, 0xFF114D05, 0x00000000, 0x00000000,
426 				0xFFA80303, 0xFF6CF073, 0xFF0E449C, 0x00000000, 0x00000000,
427 			},
428 		},
429 		.xrgb2101010_result = {
430 			.dst_pitch = 20,
431 			.expected = {
432 				0x03844672, 0x0444D414, 0x2A2F3C0C, 0x00000000, 0x00000000,
433 				0x1B1F0DCD, 0x03844672, 0x0444D414, 0x00000000, 0x00000000,
434 				0x2A20300C, 0x1B1F0DCD, 0x03844672, 0x00000000, 0x00000000,
435 			},
436 		},
437 		.argb2101010_result = {
438 			.dst_pitch = 20,
439 			.expected = {
440 				0xC3844672, 0xC444D414, 0xEA2F3C0C, 0x00000000, 0x00000000,
441 				0xDB1F0DCD, 0xC3844672, 0xC444D414, 0x00000000, 0x00000000,
442 				0xEA20300C, 0xDB1F0DCD, 0xC3844672, 0x00000000, 0x00000000,
443 			},
444 		},
445 		.mono_result = {
446 			.dst_pitch = 2,
447 			.expected = {
448 				0b100, 0b000,
449 				0b001, 0b000,
450 				0b010, 0b000,
451 			},
452 		},
453 		.swab_result = {
454 			.dst_pitch =  20,
455 			.expected = {
456 				0x9C440EA1, 0x054D11B1, 0x03F3A8C1, 0x00000000, 0x00000000,
457 				0x73F06CD1, 0x9C440EA2, 0x054D11B2, 0x00000000, 0x00000000,
458 				0x0303A8C2, 0x73F06CD2, 0x9C440EA3, 0x00000000, 0x00000000,
459 			},
460 		},
461 	},
462 };
463 
464 /*
465  * conversion_buf_size - Return the destination buffer size required to convert
466  * between formats.
467  * @dst_format: destination buffer pixel format (DRM_FORMAT_*)
468  * @dst_pitch: Number of bytes between two consecutive scanlines within dst
469  * @clip: Clip rectangle area to convert
470  *
471  * Returns:
472  * The size of the destination buffer or negative value on error.
473  */
474 static size_t conversion_buf_size(u32 dst_format, unsigned int dst_pitch,
475 				  const struct drm_rect *clip, int plane)
476 {
477 	const struct drm_format_info *dst_fi = drm_format_info(dst_format);
478 
479 	if (!dst_fi)
480 		return -EINVAL;
481 
482 	if (!dst_pitch)
483 		dst_pitch = drm_format_info_min_pitch(dst_fi, plane, drm_rect_width(clip));
484 
485 	return dst_pitch * drm_rect_height(clip);
486 }
487 
488 static u16 *le16buf_to_cpu(struct kunit *test, const __le16 *buf, size_t buf_size)
489 {
490 	u16 *dst = NULL;
491 	int n;
492 
493 	dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL);
494 	if (!dst)
495 		return NULL;
496 
497 	for (n = 0; n < buf_size; n++)
498 		dst[n] = le16_to_cpu(buf[n]);
499 
500 	return dst;
501 }
502 
503 static u32 *le32buf_to_cpu(struct kunit *test, const __le32 *buf, size_t buf_size)
504 {
505 	u32 *dst = NULL;
506 	int n;
507 
508 	dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL);
509 	if (!dst)
510 		return NULL;
511 
512 	for (n = 0; n < buf_size; n++)
513 		dst[n] = le32_to_cpu((__force __le32)buf[n]);
514 
515 	return dst;
516 }
517 
518 static __le32 *cpubuf_to_le32(struct kunit *test, const u32 *buf, size_t buf_size)
519 {
520 	__le32 *dst = NULL;
521 	int n;
522 
523 	dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL);
524 	if (!dst)
525 		return NULL;
526 
527 	for (n = 0; n < buf_size; n++)
528 		dst[n] = cpu_to_le32(buf[n]);
529 
530 	return dst;
531 }
532 
533 static void convert_xrgb8888_case_desc(struct convert_xrgb8888_case *t,
534 				       char *desc)
535 {
536 	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
537 }
538 
539 KUNIT_ARRAY_PARAM(convert_xrgb8888, convert_xrgb8888_cases,
540 		  convert_xrgb8888_case_desc);
541 
542 static void drm_test_fb_xrgb8888_to_gray8(struct kunit *test)
543 {
544 	const struct convert_xrgb8888_case *params = test->param_value;
545 	const struct convert_to_gray8_result *result = &params->gray8_result;
546 	size_t dst_size;
547 	u8 *buf = NULL;
548 	__le32 *xrgb8888 = NULL;
549 	struct iosys_map dst, src;
550 
551 	struct drm_framebuffer fb = {
552 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
553 		.pitches = { params->pitch, 0, 0 },
554 	};
555 
556 	dst_size = conversion_buf_size(DRM_FORMAT_R8, result->dst_pitch,
557 				       &params->clip, 0);
558 	KUNIT_ASSERT_GT(test, dst_size, 0);
559 
560 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
561 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
562 	iosys_map_set_vaddr(&dst, buf);
563 
564 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
565 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
566 	iosys_map_set_vaddr(&src, xrgb8888);
567 
568 	const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ?
569 		NULL : &result->dst_pitch;
570 
571 	drm_fb_xrgb8888_to_gray8(&dst, dst_pitch, &src, &fb, &params->clip);
572 
573 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
574 }
575 
576 static void drm_test_fb_xrgb8888_to_rgb332(struct kunit *test)
577 {
578 	const struct convert_xrgb8888_case *params = test->param_value;
579 	const struct convert_to_rgb332_result *result = &params->rgb332_result;
580 	size_t dst_size;
581 	u8 *buf = NULL;
582 	__le32 *xrgb8888 = NULL;
583 	struct iosys_map dst, src;
584 
585 	struct drm_framebuffer fb = {
586 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
587 		.pitches = { params->pitch, 0, 0 },
588 	};
589 
590 	dst_size = conversion_buf_size(DRM_FORMAT_RGB332, result->dst_pitch,
591 				       &params->clip, 0);
592 	KUNIT_ASSERT_GT(test, dst_size, 0);
593 
594 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
595 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
596 	iosys_map_set_vaddr(&dst, buf);
597 
598 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
599 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
600 	iosys_map_set_vaddr(&src, xrgb8888);
601 
602 	const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ?
603 		NULL : &result->dst_pitch;
604 
605 	drm_fb_xrgb8888_to_rgb332(&dst, dst_pitch, &src, &fb, &params->clip);
606 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
607 }
608 
609 static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test)
610 {
611 	const struct convert_xrgb8888_case *params = test->param_value;
612 	const struct convert_to_rgb565_result *result = &params->rgb565_result;
613 	size_t dst_size;
614 	u16 *buf = NULL;
615 	__le32 *xrgb8888 = NULL;
616 	struct iosys_map dst, src;
617 
618 	struct drm_framebuffer fb = {
619 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
620 		.pitches = { params->pitch, 0, 0 },
621 	};
622 
623 	dst_size = conversion_buf_size(DRM_FORMAT_RGB565, result->dst_pitch,
624 				       &params->clip, 0);
625 	KUNIT_ASSERT_GT(test, dst_size, 0);
626 
627 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
628 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
629 	iosys_map_set_vaddr(&dst, buf);
630 
631 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
632 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
633 	iosys_map_set_vaddr(&src, xrgb8888);
634 
635 	const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ?
636 		NULL : &result->dst_pitch;
637 
638 	drm_fb_xrgb8888_to_rgb565(&dst, dst_pitch, &src, &fb, &params->clip, false);
639 	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
640 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
641 
642 	buf = dst.vaddr; /* restore original value of buf */
643 	drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, true);
644 	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
645 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected_swab, dst_size);
646 }
647 
648 static void drm_test_fb_xrgb8888_to_xrgb1555(struct kunit *test)
649 {
650 	const struct convert_xrgb8888_case *params = test->param_value;
651 	const struct convert_to_xrgb1555_result *result = &params->xrgb1555_result;
652 	size_t dst_size;
653 	u16 *buf = NULL;
654 	__le32 *xrgb8888 = NULL;
655 	struct iosys_map dst, src;
656 
657 	struct drm_framebuffer fb = {
658 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
659 		.pitches = { params->pitch, 0, 0 },
660 	};
661 
662 	dst_size = conversion_buf_size(DRM_FORMAT_XRGB1555, result->dst_pitch,
663 				       &params->clip, 0);
664 	KUNIT_ASSERT_GT(test, dst_size, 0);
665 
666 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
667 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
668 	iosys_map_set_vaddr(&dst, buf);
669 
670 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
671 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
672 	iosys_map_set_vaddr(&src, xrgb8888);
673 
674 	const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ?
675 		NULL : &result->dst_pitch;
676 
677 	drm_fb_xrgb8888_to_xrgb1555(&dst, dst_pitch, &src, &fb, &params->clip);
678 	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
679 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
680 }
681 
682 static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test)
683 {
684 	const struct convert_xrgb8888_case *params = test->param_value;
685 	const struct convert_to_argb1555_result *result = &params->argb1555_result;
686 	size_t dst_size;
687 	u16 *buf = NULL;
688 	__le32 *xrgb8888 = NULL;
689 	struct iosys_map dst, src;
690 
691 	struct drm_framebuffer fb = {
692 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
693 		.pitches = { params->pitch, 0, 0 },
694 	};
695 
696 	dst_size = conversion_buf_size(DRM_FORMAT_ARGB1555, result->dst_pitch,
697 				       &params->clip, 0);
698 	KUNIT_ASSERT_GT(test, dst_size, 0);
699 
700 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
701 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
702 	iosys_map_set_vaddr(&dst, buf);
703 
704 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
705 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
706 	iosys_map_set_vaddr(&src, xrgb8888);
707 
708 	const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ?
709 		NULL : &result->dst_pitch;
710 
711 	drm_fb_xrgb8888_to_argb1555(&dst, dst_pitch, &src, &fb, &params->clip);
712 	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
713 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
714 }
715 
716 static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test)
717 {
718 	const struct convert_xrgb8888_case *params = test->param_value;
719 	const struct convert_to_rgba5551_result *result = &params->rgba5551_result;
720 	size_t dst_size;
721 	u16 *buf = NULL;
722 	__le32 *xrgb8888 = NULL;
723 	struct iosys_map dst, src;
724 
725 	struct drm_framebuffer fb = {
726 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
727 		.pitches = { params->pitch, 0, 0 },
728 	};
729 
730 	dst_size = conversion_buf_size(DRM_FORMAT_RGBA5551, result->dst_pitch,
731 				       &params->clip, 0);
732 	KUNIT_ASSERT_GT(test, dst_size, 0);
733 
734 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
735 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
736 	iosys_map_set_vaddr(&dst, buf);
737 
738 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
739 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
740 	iosys_map_set_vaddr(&src, xrgb8888);
741 
742 	const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ?
743 		NULL : &result->dst_pitch;
744 
745 	drm_fb_xrgb8888_to_rgba5551(&dst, dst_pitch, &src, &fb, &params->clip);
746 	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
747 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
748 }
749 
750 static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)
751 {
752 	const struct convert_xrgb8888_case *params = test->param_value;
753 	const struct convert_to_rgb888_result *result = &params->rgb888_result;
754 	size_t dst_size;
755 	u8 *buf = NULL;
756 	__le32 *xrgb8888 = NULL;
757 	struct iosys_map dst, src;
758 
759 	struct drm_framebuffer fb = {
760 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
761 		.pitches = { params->pitch, 0, 0 },
762 	};
763 
764 	dst_size = conversion_buf_size(DRM_FORMAT_RGB888, result->dst_pitch,
765 				       &params->clip, 0);
766 	KUNIT_ASSERT_GT(test, dst_size, 0);
767 
768 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
769 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
770 	iosys_map_set_vaddr(&dst, buf);
771 
772 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
773 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
774 	iosys_map_set_vaddr(&src, xrgb8888);
775 
776 	/*
777 	 * RGB888 expected results are already in little-endian
778 	 * order, so there's no need to convert the test output.
779 	 */
780 	const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ?
781 		NULL : &result->dst_pitch;
782 
783 	drm_fb_xrgb8888_to_rgb888(&dst, dst_pitch, &src, &fb, &params->clip);
784 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
785 }
786 
787 static void drm_test_fb_xrgb8888_to_argb8888(struct kunit *test)
788 {
789 	const struct convert_xrgb8888_case *params = test->param_value;
790 	const struct convert_to_argb8888_result *result = &params->argb8888_result;
791 	size_t dst_size;
792 	u32 *buf = NULL;
793 	__le32 *xrgb8888 = NULL;
794 	struct iosys_map dst, src;
795 
796 	struct drm_framebuffer fb = {
797 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
798 		.pitches = { params->pitch, 0, 0 },
799 	};
800 
801 	dst_size = conversion_buf_size(DRM_FORMAT_ARGB8888,
802 				       result->dst_pitch, &params->clip, 0);
803 	KUNIT_ASSERT_GT(test, dst_size, 0);
804 
805 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
806 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
807 	iosys_map_set_vaddr(&dst, buf);
808 
809 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
810 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
811 	iosys_map_set_vaddr(&src, xrgb8888);
812 
813 	const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ?
814 		NULL : &result->dst_pitch;
815 
816 	drm_fb_xrgb8888_to_argb8888(&dst, dst_pitch, &src, &fb, &params->clip);
817 	buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));
818 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
819 }
820 
821 static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)
822 {
823 	const struct convert_xrgb8888_case *params = test->param_value;
824 	const struct convert_to_xrgb2101010_result *result = &params->xrgb2101010_result;
825 	size_t dst_size;
826 	u32 *buf = NULL;
827 	__le32 *xrgb8888 = NULL;
828 	struct iosys_map dst, src;
829 
830 	struct drm_framebuffer fb = {
831 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
832 		.pitches = { params->pitch, 0, 0 },
833 	};
834 
835 	dst_size = conversion_buf_size(DRM_FORMAT_XRGB2101010,
836 				       result->dst_pitch, &params->clip, 0);
837 	KUNIT_ASSERT_GT(test, dst_size, 0);
838 
839 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
840 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
841 	iosys_map_set_vaddr(&dst, buf);
842 
843 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
844 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
845 	iosys_map_set_vaddr(&src, xrgb8888);
846 
847 	const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ?
848 		NULL : &result->dst_pitch;
849 
850 	drm_fb_xrgb8888_to_xrgb2101010(&dst, dst_pitch, &src, &fb, &params->clip);
851 	buf = le32buf_to_cpu(test, buf, dst_size / sizeof(u32));
852 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
853 }
854 
855 static void drm_test_fb_xrgb8888_to_argb2101010(struct kunit *test)
856 {
857 	const struct convert_xrgb8888_case *params = test->param_value;
858 	const struct convert_to_argb2101010_result *result = &params->argb2101010_result;
859 	size_t dst_size;
860 	u32 *buf = NULL;
861 	__le32 *xrgb8888 = NULL;
862 	struct iosys_map dst, src;
863 
864 	struct drm_framebuffer fb = {
865 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
866 		.pitches = { params->pitch, 0, 0 },
867 	};
868 
869 	dst_size = conversion_buf_size(DRM_FORMAT_ARGB2101010,
870 				       result->dst_pitch, &params->clip, 0);
871 	KUNIT_ASSERT_GT(test, dst_size, 0);
872 
873 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
874 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
875 	iosys_map_set_vaddr(&dst, buf);
876 
877 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
878 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
879 	iosys_map_set_vaddr(&src, xrgb8888);
880 
881 	const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ?
882 		NULL : &result->dst_pitch;
883 
884 	drm_fb_xrgb8888_to_argb2101010(&dst, dst_pitch, &src, &fb, &params->clip);
885 	buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));
886 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
887 }
888 
889 static void drm_test_fb_xrgb8888_to_mono(struct kunit *test)
890 {
891 	const struct convert_xrgb8888_case *params = test->param_value;
892 	const struct convert_to_mono_result *result = &params->mono_result;
893 	size_t dst_size;
894 	u8 *buf = NULL;
895 	__le32 *xrgb8888 = NULL;
896 	struct iosys_map dst, src;
897 
898 	struct drm_framebuffer fb = {
899 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
900 		.pitches = { params->pitch, 0, 0 },
901 	};
902 
903 	dst_size = conversion_buf_size(DRM_FORMAT_C1, result->dst_pitch, &params->clip, 0);
904 
905 	KUNIT_ASSERT_GT(test, dst_size, 0);
906 
907 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
908 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
909 	iosys_map_set_vaddr(&dst, buf);
910 
911 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
912 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
913 	iosys_map_set_vaddr(&src, xrgb8888);
914 
915 	const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ?
916 		NULL : &result->dst_pitch;
917 
918 	drm_fb_xrgb8888_to_mono(&dst, dst_pitch, &src, &fb, &params->clip);
919 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
920 }
921 
922 static void drm_test_fb_swab(struct kunit *test)
923 {
924 	const struct convert_xrgb8888_case *params = test->param_value;
925 	const struct fb_swab_result *result = &params->swab_result;
926 	size_t dst_size;
927 	u32 *buf = NULL;
928 	__le32 *xrgb8888 = NULL;
929 	struct iosys_map dst, src;
930 
931 	struct drm_framebuffer fb = {
932 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
933 		.pitches = { params->pitch, 0, 0 },
934 	};
935 
936 	dst_size = conversion_buf_size(DRM_FORMAT_XRGB8888, result->dst_pitch, &params->clip, 0);
937 
938 	KUNIT_ASSERT_GT(test, dst_size, 0);
939 
940 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
941 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
942 	iosys_map_set_vaddr(&dst, buf);
943 
944 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
945 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
946 	iosys_map_set_vaddr(&src, xrgb8888);
947 
948 	const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ?
949 		NULL : &result->dst_pitch;
950 
951 	drm_fb_swab(&dst, dst_pitch, &src, &fb, &params->clip, false);
952 	buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));
953 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
954 }
955 
956 struct clip_offset_case {
957 	const char *name;
958 	unsigned int pitch;
959 	u32 format;
960 	struct drm_rect clip;
961 	unsigned int expected_offset;
962 };
963 
964 static struct clip_offset_case clip_offset_cases[] = {
965 	{
966 		.name = "pass through",
967 		.pitch = TEST_USE_DEFAULT_PITCH,
968 		.format = DRM_FORMAT_XRGB8888,
969 		.clip = DRM_RECT_INIT(0, 0, 3, 3),
970 		.expected_offset = 0
971 	},
972 	{
973 		.name = "horizontal offset",
974 		.pitch = TEST_USE_DEFAULT_PITCH,
975 		.format = DRM_FORMAT_XRGB8888,
976 		.clip = DRM_RECT_INIT(1, 0, 3, 3),
977 		.expected_offset = 4,
978 	},
979 	{
980 		.name = "vertical offset",
981 		.pitch = TEST_USE_DEFAULT_PITCH,
982 		.format = DRM_FORMAT_XRGB8888,
983 		.clip = DRM_RECT_INIT(0, 1, 3, 3),
984 		.expected_offset = 12,
985 	},
986 	{
987 		.name = "horizontal and vertical offset",
988 		.pitch = TEST_USE_DEFAULT_PITCH,
989 		.format = DRM_FORMAT_XRGB8888,
990 		.clip = DRM_RECT_INIT(1, 1, 3, 3),
991 		.expected_offset = 16,
992 	},
993 	{
994 		.name = "horizontal offset (custom pitch)",
995 		.pitch = 20,
996 		.format = DRM_FORMAT_XRGB8888,
997 		.clip = DRM_RECT_INIT(1, 0, 3, 3),
998 		.expected_offset = 4,
999 	},
1000 	{
1001 		.name = "vertical offset (custom pitch)",
1002 		.pitch = 20,
1003 		.format = DRM_FORMAT_XRGB8888,
1004 		.clip = DRM_RECT_INIT(0, 1, 3, 3),
1005 		.expected_offset = 20,
1006 	},
1007 	{
1008 		.name = "horizontal and vertical offset (custom pitch)",
1009 		.pitch = 20,
1010 		.format = DRM_FORMAT_XRGB8888,
1011 		.clip = DRM_RECT_INIT(1, 1, 3, 3),
1012 		.expected_offset = 24,
1013 	},
1014 };
1015 
1016 static void clip_offset_case_desc(struct clip_offset_case *t, char *desc)
1017 {
1018 	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
1019 }
1020 
1021 KUNIT_ARRAY_PARAM(clip_offset, clip_offset_cases, clip_offset_case_desc);
1022 
1023 static void drm_test_fb_clip_offset(struct kunit *test)
1024 {
1025 	const struct clip_offset_case *params = test->param_value;
1026 	const struct drm_format_info *format_info = drm_format_info(params->format);
1027 
1028 	unsigned int offset;
1029 	unsigned int pitch = params->pitch;
1030 
1031 	if (pitch == TEST_USE_DEFAULT_PITCH)
1032 		pitch = drm_format_info_min_pitch(format_info, 0,
1033 						  drm_rect_width(&params->clip));
1034 
1035 	/*
1036 	 * Assure that the pitch is not zero, because this will inevitable cause the
1037 	 * wrong expected result
1038 	 */
1039 	KUNIT_ASSERT_NE(test, pitch, 0);
1040 
1041 	offset = drm_fb_clip_offset(pitch, format_info, &params->clip);
1042 
1043 	KUNIT_EXPECT_EQ(test, offset, params->expected_offset);
1044 }
1045 
1046 struct fb_build_fourcc_list_case {
1047 	const char *name;
1048 	u32 native_fourccs[TEST_BUF_SIZE];
1049 	size_t native_fourccs_size;
1050 	u32 expected[TEST_BUF_SIZE];
1051 	size_t expected_fourccs_size;
1052 };
1053 
1054 static struct fb_build_fourcc_list_case fb_build_fourcc_list_cases[] = {
1055 	{
1056 		.name = "no native formats",
1057 		.native_fourccs = { },
1058 		.native_fourccs_size = 0,
1059 		.expected = { DRM_FORMAT_XRGB8888 },
1060 		.expected_fourccs_size = 1,
1061 	},
1062 	{
1063 		.name = "XRGB8888 as native format",
1064 		.native_fourccs = { DRM_FORMAT_XRGB8888 },
1065 		.native_fourccs_size = 1,
1066 		.expected = { DRM_FORMAT_XRGB8888 },
1067 		.expected_fourccs_size = 1,
1068 	},
1069 	{
1070 		.name = "remove duplicates",
1071 		.native_fourccs = {
1072 			DRM_FORMAT_XRGB8888,
1073 			DRM_FORMAT_XRGB8888,
1074 			DRM_FORMAT_RGB888,
1075 			DRM_FORMAT_RGB888,
1076 			DRM_FORMAT_RGB888,
1077 			DRM_FORMAT_XRGB8888,
1078 			DRM_FORMAT_RGB888,
1079 			DRM_FORMAT_RGB565,
1080 			DRM_FORMAT_RGB888,
1081 			DRM_FORMAT_XRGB8888,
1082 			DRM_FORMAT_RGB565,
1083 			DRM_FORMAT_RGB565,
1084 			DRM_FORMAT_XRGB8888,
1085 		},
1086 		.native_fourccs_size = 11,
1087 		.expected = {
1088 			DRM_FORMAT_XRGB8888,
1089 			DRM_FORMAT_RGB888,
1090 			DRM_FORMAT_RGB565,
1091 		},
1092 		.expected_fourccs_size = 3,
1093 	},
1094 	{
1095 		.name = "convert alpha formats",
1096 		.native_fourccs = {
1097 			DRM_FORMAT_ARGB1555,
1098 			DRM_FORMAT_ABGR1555,
1099 			DRM_FORMAT_RGBA5551,
1100 			DRM_FORMAT_BGRA5551,
1101 			DRM_FORMAT_ARGB8888,
1102 			DRM_FORMAT_ABGR8888,
1103 			DRM_FORMAT_RGBA8888,
1104 			DRM_FORMAT_BGRA8888,
1105 			DRM_FORMAT_ARGB2101010,
1106 			DRM_FORMAT_ABGR2101010,
1107 			DRM_FORMAT_RGBA1010102,
1108 			DRM_FORMAT_BGRA1010102,
1109 		},
1110 		.native_fourccs_size = 12,
1111 		.expected = {
1112 			DRM_FORMAT_XRGB1555,
1113 			DRM_FORMAT_XBGR1555,
1114 			DRM_FORMAT_RGBX5551,
1115 			DRM_FORMAT_BGRX5551,
1116 			DRM_FORMAT_XRGB8888,
1117 			DRM_FORMAT_XBGR8888,
1118 			DRM_FORMAT_RGBX8888,
1119 			DRM_FORMAT_BGRX8888,
1120 			DRM_FORMAT_XRGB2101010,
1121 			DRM_FORMAT_XBGR2101010,
1122 			DRM_FORMAT_RGBX1010102,
1123 			DRM_FORMAT_BGRX1010102,
1124 		},
1125 		.expected_fourccs_size = 12,
1126 	},
1127 	{
1128 		.name = "random formats",
1129 		.native_fourccs = {
1130 			DRM_FORMAT_Y212,
1131 			DRM_FORMAT_ARGB1555,
1132 			DRM_FORMAT_ABGR16161616F,
1133 			DRM_FORMAT_C8,
1134 			DRM_FORMAT_BGR888,
1135 			DRM_FORMAT_XRGB1555,
1136 			DRM_FORMAT_RGBA5551,
1137 			DRM_FORMAT_BGR565_A8,
1138 			DRM_FORMAT_R10,
1139 			DRM_FORMAT_XYUV8888,
1140 		},
1141 		.native_fourccs_size = 10,
1142 		.expected = {
1143 			DRM_FORMAT_Y212,
1144 			DRM_FORMAT_XRGB1555,
1145 			DRM_FORMAT_ABGR16161616F,
1146 			DRM_FORMAT_C8,
1147 			DRM_FORMAT_BGR888,
1148 			DRM_FORMAT_RGBX5551,
1149 			DRM_FORMAT_BGR565_A8,
1150 			DRM_FORMAT_R10,
1151 			DRM_FORMAT_XYUV8888,
1152 			DRM_FORMAT_XRGB8888,
1153 		},
1154 		.expected_fourccs_size = 10,
1155 	},
1156 };
1157 
1158 static void fb_build_fourcc_list_case_desc(struct fb_build_fourcc_list_case *t, char *desc)
1159 {
1160 	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
1161 }
1162 
1163 KUNIT_ARRAY_PARAM(fb_build_fourcc_list, fb_build_fourcc_list_cases, fb_build_fourcc_list_case_desc);
1164 
1165 static void drm_test_fb_build_fourcc_list(struct kunit *test)
1166 {
1167 	const struct fb_build_fourcc_list_case *params = test->param_value;
1168 	u32 fourccs_out[TEST_BUF_SIZE] = {0};
1169 	size_t nfourccs_out;
1170 	struct drm_device *drm;
1171 	struct device *dev;
1172 
1173 	dev = drm_kunit_helper_alloc_device(test);
1174 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
1175 
1176 	drm = __drm_kunit_helper_alloc_drm_device(test, dev, sizeof(*drm), 0, DRIVER_MODESET);
1177 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
1178 
1179 	nfourccs_out = drm_fb_build_fourcc_list(drm, params->native_fourccs,
1180 						params->native_fourccs_size,
1181 						fourccs_out, TEST_BUF_SIZE);
1182 
1183 	KUNIT_EXPECT_EQ(test, nfourccs_out, params->expected_fourccs_size);
1184 	KUNIT_EXPECT_MEMEQ(test, fourccs_out, params->expected, TEST_BUF_SIZE);
1185 }
1186 
1187 struct fb_memcpy_case {
1188 	const char *name;
1189 	u32 format;
1190 	struct drm_rect clip;
1191 	unsigned int src_pitches[DRM_FORMAT_MAX_PLANES];
1192 	const u32 src[DRM_FORMAT_MAX_PLANES][TEST_BUF_SIZE];
1193 	unsigned int dst_pitches[DRM_FORMAT_MAX_PLANES];
1194 	const u32 expected[DRM_FORMAT_MAX_PLANES][TEST_BUF_SIZE];
1195 };
1196 
1197 /* The `src` and `expected` buffers are u32 arrays. To deal with planes that
1198  * have a cpp != 4 the values are stored together on the same u32 number in a
1199  * way so the order in memory is correct in a little-endian machine.
1200  *
1201  * Because of that, on some occasions, parts of a u32 will not be part of the
1202  * test, to make this explicit the 0xFF byte is used on those parts.
1203  */
1204 
1205 static struct fb_memcpy_case fb_memcpy_cases[] = {
1206 	{
1207 		.name = "single_pixel_source_buffer",
1208 		.format = DRM_FORMAT_XRGB8888,
1209 		.clip = DRM_RECT_INIT(0, 0, 1, 1),
1210 		.src_pitches = { 1 * 4 },
1211 		.src = {{ 0x01020304 }},
1212 		.dst_pitches = { TEST_USE_DEFAULT_PITCH },
1213 		.expected = {{ 0x01020304 }},
1214 	},
1215 	{
1216 		.name = "single_pixel_source_buffer",
1217 		.format = DRM_FORMAT_XRGB8888_A8,
1218 		.clip = DRM_RECT_INIT(0, 0, 1, 1),
1219 		.src_pitches = { 1 * 4, 1 },
1220 		.src = {
1221 			{ 0x01020304 },
1222 			{ 0xFFFFFF01 },
1223 		},
1224 		.dst_pitches = { TEST_USE_DEFAULT_PITCH },
1225 		.expected = {
1226 			{ 0x01020304 },
1227 			{ 0x00000001 },
1228 		},
1229 	},
1230 	{
1231 		.name = "single_pixel_source_buffer",
1232 		.format = DRM_FORMAT_YUV444,
1233 		.clip = DRM_RECT_INIT(0, 0, 1, 1),
1234 		.src_pitches = { 1, 1, 1 },
1235 		.src = {
1236 			{ 0xFFFFFF01 },
1237 			{ 0xFFFFFF01 },
1238 			{ 0xFFFFFF01 },
1239 		},
1240 		.dst_pitches = { TEST_USE_DEFAULT_PITCH },
1241 		.expected = {
1242 			{ 0x00000001 },
1243 			{ 0x00000001 },
1244 			{ 0x00000001 },
1245 		},
1246 	},
1247 	{
1248 		.name = "single_pixel_clip_rectangle",
1249 		.format = DRM_FORMAT_XBGR8888,
1250 		.clip = DRM_RECT_INIT(1, 1, 1, 1),
1251 		.src_pitches = { 2 * 4 },
1252 		.src = {
1253 			{
1254 				0x00000000, 0x00000000,
1255 				0x00000000, 0x01020304,
1256 			},
1257 		},
1258 		.dst_pitches = { TEST_USE_DEFAULT_PITCH },
1259 		.expected = {
1260 			{ 0x01020304 },
1261 		},
1262 	},
1263 	{
1264 		.name = "single_pixel_clip_rectangle",
1265 		.format = DRM_FORMAT_XRGB8888_A8,
1266 		.clip = DRM_RECT_INIT(1, 1, 1, 1),
1267 		.src_pitches = { 2 * 4, 2 * 1 },
1268 		.src = {
1269 			{
1270 				0x00000000, 0x00000000,
1271 				0x00000000, 0x01020304,
1272 			},
1273 			{ 0x01000000 },
1274 		},
1275 		.dst_pitches = { TEST_USE_DEFAULT_PITCH },
1276 		.expected = {
1277 			{ 0x01020304 },
1278 			{ 0x00000001 },
1279 		},
1280 	},
1281 	{
1282 		.name = "single_pixel_clip_rectangle",
1283 		.format = DRM_FORMAT_YUV444,
1284 		.clip = DRM_RECT_INIT(1, 1, 1, 1),
1285 		.src_pitches = { 2 * 1, 2 * 1, 2 * 1 },
1286 		.src = {
1287 			{ 0x01000000 },
1288 			{ 0x01000000 },
1289 			{ 0x01000000 },
1290 		},
1291 		.dst_pitches = { TEST_USE_DEFAULT_PITCH },
1292 		.expected = {
1293 			{ 0x00000001 },
1294 			{ 0x00000001 },
1295 			{ 0x00000001 },
1296 		},
1297 	},
1298 	{
1299 		.name = "well_known_colors",
1300 		.format = DRM_FORMAT_XBGR8888,
1301 		.clip = DRM_RECT_INIT(1, 1, 2, 4),
1302 		.src_pitches = { 4 * 4 },
1303 		.src = {
1304 			{
1305 				0x00000000, 0x00000000, 0x00000000, 0x00000000,
1306 				0x00000000, 0x11FFFFFF, 0x22000000, 0x00000000,
1307 				0x00000000, 0x33FF0000, 0x4400FF00, 0x00000000,
1308 				0x00000000, 0x550000FF, 0x66FF00FF, 0x00000000,
1309 				0x00000000, 0x77FFFF00, 0x8800FFFF, 0x00000000,
1310 			},
1311 		},
1312 		.dst_pitches = { TEST_USE_DEFAULT_PITCH },
1313 		.expected = {
1314 			{
1315 				0x11FFFFFF, 0x22000000,
1316 				0x33FF0000, 0x4400FF00,
1317 				0x550000FF, 0x66FF00FF,
1318 				0x77FFFF00, 0x8800FFFF,
1319 			},
1320 		},
1321 	},
1322 	{
1323 		.name = "well_known_colors",
1324 		.format = DRM_FORMAT_XRGB8888_A8,
1325 		.clip = DRM_RECT_INIT(1, 1, 2, 4),
1326 		.src_pitches = { 4 * 4, 4 * 1 },
1327 		.src = {
1328 			{
1329 				0x00000000, 0x00000000, 0x00000000, 0x00000000,
1330 				0x00000000, 0xFFFFFFFF, 0xFF000000, 0x00000000,
1331 				0x00000000, 0xFFFF0000, 0xFF00FF00, 0x00000000,
1332 				0x00000000, 0xFF0000FF, 0xFFFF00FF, 0x00000000,
1333 				0x00000000, 0xFFFFFF00, 0xFF00FFFF, 0x00000000,
1334 			},
1335 			{
1336 				0x00000000,
1337 				0x00221100,
1338 				0x00443300,
1339 				0x00665500,
1340 				0x00887700,
1341 			},
1342 		},
1343 		.dst_pitches = { TEST_USE_DEFAULT_PITCH },
1344 		.expected = {
1345 			{
1346 				0xFFFFFFFF, 0xFF000000,
1347 				0xFFFF0000, 0xFF00FF00,
1348 				0xFF0000FF, 0xFFFF00FF,
1349 				0xFFFFFF00, 0xFF00FFFF,
1350 			},
1351 			{
1352 				0x44332211,
1353 				0x88776655,
1354 			},
1355 		},
1356 	},
1357 	{
1358 		.name = "well_known_colors",
1359 		.format = DRM_FORMAT_YUV444,
1360 		.clip = DRM_RECT_INIT(1, 1, 2, 4),
1361 		.src_pitches = { 4 * 1, 4 * 1, 4 * 1 },
1362 		.src = {
1363 			{
1364 				0x00000000,
1365 				0x0000FF00,
1366 				0x00954C00,
1367 				0x00691D00,
1368 				0x00B2E100,
1369 			},
1370 			{
1371 				0x00000000,
1372 				0x00000000,
1373 				0x00BEDE00,
1374 				0x00436500,
1375 				0x00229B00,
1376 			},
1377 			{
1378 				0x00000000,
1379 				0x00000000,
1380 				0x007E9C00,
1381 				0x0083E700,
1382 				0x00641A00,
1383 			},
1384 		},
1385 		.dst_pitches = { TEST_USE_DEFAULT_PITCH },
1386 		.expected = {
1387 			{
1388 				0x954C00FF,
1389 				0xB2E1691D,
1390 			},
1391 			{
1392 				0xBEDE0000,
1393 				0x229B4365,
1394 			},
1395 			{
1396 				0x7E9C0000,
1397 				0x641A83E7,
1398 			},
1399 		},
1400 	},
1401 	{
1402 		.name = "destination_pitch",
1403 		.format = DRM_FORMAT_XBGR8888,
1404 		.clip = DRM_RECT_INIT(0, 0, 3, 3),
1405 		.src_pitches = { 3 * 4 },
1406 		.src = {
1407 			{
1408 				0xA10E449C, 0xB1114D05, 0xC1A8F303,
1409 				0xD16CF073, 0xA20E449C, 0xB2114D05,
1410 				0xC2A80303, 0xD26CF073, 0xA30E449C,
1411 			},
1412 		},
1413 		.dst_pitches = { 5 * 4 },
1414 		.expected = {
1415 			{
1416 				0xA10E449C, 0xB1114D05, 0xC1A8F303, 0x00000000, 0x00000000,
1417 				0xD16CF073, 0xA20E449C, 0xB2114D05, 0x00000000, 0x00000000,
1418 				0xC2A80303, 0xD26CF073, 0xA30E449C, 0x00000000, 0x00000000,
1419 			},
1420 		},
1421 	},
1422 	{
1423 		.name = "destination_pitch",
1424 		.format = DRM_FORMAT_XRGB8888_A8,
1425 		.clip = DRM_RECT_INIT(0, 0, 3, 3),
1426 		.src_pitches = { 3 * 4, 3 * 1 },
1427 		.src = {
1428 			{
1429 				0xFF0E449C, 0xFF114D05, 0xFFA8F303,
1430 				0xFF6CF073, 0xFF0E449C, 0xFF114D05,
1431 				0xFFA80303, 0xFF6CF073, 0xFF0E449C,
1432 			},
1433 			{
1434 				0xB2C1B1A1,
1435 				0xD2A3D1A2,
1436 				0xFFFFFFC2,
1437 			},
1438 		},
1439 		.dst_pitches = { 5 * 4, 5 * 1 },
1440 		.expected = {
1441 			{
1442 				0xFF0E449C, 0xFF114D05, 0xFFA8F303, 0x00000000, 0x00000000,
1443 				0xFF6CF073, 0xFF0E449C, 0xFF114D05, 0x00000000, 0x00000000,
1444 				0xFFA80303, 0xFF6CF073, 0xFF0E449C, 0x00000000, 0x00000000,
1445 			},
1446 			{
1447 				0x00C1B1A1,
1448 				0xD1A2B200,
1449 				0xD2A30000,
1450 				0xFF0000C2,
1451 			},
1452 		},
1453 	},
1454 	{
1455 		.name = "destination_pitch",
1456 		.format = DRM_FORMAT_YUV444,
1457 		.clip = DRM_RECT_INIT(0, 0, 3, 3),
1458 		.src_pitches = { 3 * 1, 3 * 1, 3 * 1 },
1459 		.src = {
1460 			{
1461 				0xBAC1323D,
1462 				0xBA34323D,
1463 				0xFFFFFF3D,
1464 			},
1465 			{
1466 				0xE1ABEC2A,
1467 				0xE1EAEC2A,
1468 				0xFFFFFF2A,
1469 			},
1470 			{
1471 				0xBCEBE4D7,
1472 				0xBC65E4D7,
1473 				0xFFFFFFD7,
1474 			},
1475 		},
1476 		.dst_pitches = { 5 * 1, 5 * 1, 5 * 1 },
1477 		.expected = {
1478 			{
1479 				0x00C1323D,
1480 				0x323DBA00,
1481 				0xBA340000,
1482 				0xFF00003D,
1483 			},
1484 			{
1485 				0x00ABEC2A,
1486 				0xEC2AE100,
1487 				0xE1EA0000,
1488 				0xFF00002A,
1489 			},
1490 			{
1491 				0x00EBE4D7,
1492 				0xE4D7BC00,
1493 				0xBC650000,
1494 				0xFF0000D7,
1495 			},
1496 		},
1497 	},
1498 };
1499 
1500 static void fb_memcpy_case_desc(struct fb_memcpy_case *t, char *desc)
1501 {
1502 	snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s: %p4cc", t->name, &t->format);
1503 }
1504 
1505 KUNIT_ARRAY_PARAM(fb_memcpy, fb_memcpy_cases, fb_memcpy_case_desc);
1506 
1507 static void drm_test_fb_memcpy(struct kunit *test)
1508 {
1509 	const struct fb_memcpy_case *params = test->param_value;
1510 	size_t dst_size[DRM_FORMAT_MAX_PLANES] = { 0 };
1511 	u32 *buf[DRM_FORMAT_MAX_PLANES] = { 0 };
1512 	__le32 *src_cp[DRM_FORMAT_MAX_PLANES] = { 0 };
1513 	__le32 *expected[DRM_FORMAT_MAX_PLANES] = { 0 };
1514 	struct iosys_map dst[DRM_FORMAT_MAX_PLANES];
1515 	struct iosys_map src[DRM_FORMAT_MAX_PLANES];
1516 
1517 	struct drm_framebuffer fb = {
1518 		.format = drm_format_info(params->format),
1519 	};
1520 
1521 	memcpy(fb.pitches, params->src_pitches, DRM_FORMAT_MAX_PLANES * sizeof(int));
1522 
1523 	for (size_t i = 0; i < fb.format->num_planes; i++) {
1524 		dst_size[i] = conversion_buf_size(params->format, params->dst_pitches[i],
1525 						  &params->clip, i);
1526 		KUNIT_ASSERT_GT(test, dst_size[i], 0);
1527 
1528 		buf[i] = kunit_kzalloc(test, dst_size[i], GFP_KERNEL);
1529 		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf[i]);
1530 		iosys_map_set_vaddr(&dst[i], buf[i]);
1531 
1532 		src_cp[i] = cpubuf_to_le32(test, params->src[i], TEST_BUF_SIZE);
1533 		iosys_map_set_vaddr(&src[i], src_cp[i]);
1534 	}
1535 
1536 	const unsigned int *dst_pitches = params->dst_pitches[0] == TEST_USE_DEFAULT_PITCH ? NULL :
1537 		params->dst_pitches;
1538 
1539 	drm_fb_memcpy(dst, dst_pitches, src, &fb, &params->clip);
1540 
1541 	for (size_t i = 0; i < fb.format->num_planes; i++) {
1542 		expected[i] = cpubuf_to_le32(test, params->expected[i], TEST_BUF_SIZE);
1543 		KUNIT_EXPECT_MEMEQ_MSG(test, buf[i], expected[i], dst_size[i],
1544 				       "Failed expectation on plane %zu", i);
1545 	}
1546 }
1547 
1548 static struct kunit_case drm_format_helper_test_cases[] = {
1549 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_gray8, convert_xrgb8888_gen_params),
1550 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb332, convert_xrgb8888_gen_params),
1551 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb565, convert_xrgb8888_gen_params),
1552 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb1555, convert_xrgb8888_gen_params),
1553 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb1555, convert_xrgb8888_gen_params),
1554 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgba5551, convert_xrgb8888_gen_params),
1555 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb888, convert_xrgb8888_gen_params),
1556 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb8888, convert_xrgb8888_gen_params),
1557 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb2101010, convert_xrgb8888_gen_params),
1558 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb2101010, convert_xrgb8888_gen_params),
1559 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_mono, convert_xrgb8888_gen_params),
1560 	KUNIT_CASE_PARAM(drm_test_fb_swab, convert_xrgb8888_gen_params),
1561 	KUNIT_CASE_PARAM(drm_test_fb_clip_offset, clip_offset_gen_params),
1562 	KUNIT_CASE_PARAM(drm_test_fb_build_fourcc_list, fb_build_fourcc_list_gen_params),
1563 	KUNIT_CASE_PARAM(drm_test_fb_memcpy, fb_memcpy_gen_params),
1564 	{}
1565 };
1566 
1567 static struct kunit_suite drm_format_helper_test_suite = {
1568 	.name = "drm_format_helper_test",
1569 	.test_cases = drm_format_helper_test_cases,
1570 };
1571 
1572 kunit_test_suite(drm_format_helper_test_suite);
1573 
1574 MODULE_DESCRIPTION("KUnit tests for the drm_format_helper APIs");
1575 MODULE_LICENSE("GPL");
1576 MODULE_AUTHOR("José Expósito <jose.exposito89@gmail.com>");
1577