1 // SPDX-License-Identifier: GPL-2.0+
2 
3 #include <kunit/test.h>
4 
5 #include <drm/drm_device.h>
6 #include <drm/drm_file.h>
7 #include <drm/drm_format_helper.h>
8 #include <drm/drm_fourcc.h>
9 #include <drm/drm_framebuffer.h>
10 #include <drm/drm_gem_framebuffer_helper.h>
11 #include <drm/drm_mode.h>
12 #include <drm/drm_print.h>
13 #include <drm/drm_rect.h>
14 
15 #include "../drm_crtc_internal.h"
16 
17 #define TEST_BUF_SIZE 50
18 
19 struct convert_to_gray8_result {
20 	unsigned int dst_pitch;
21 	const u8 expected[TEST_BUF_SIZE];
22 };
23 
24 struct convert_to_rgb332_result {
25 	unsigned int dst_pitch;
26 	const u8 expected[TEST_BUF_SIZE];
27 };
28 
29 struct convert_to_rgb565_result {
30 	unsigned int dst_pitch;
31 	const u16 expected[TEST_BUF_SIZE];
32 	const u16 expected_swab[TEST_BUF_SIZE];
33 };
34 
35 struct convert_to_xrgb1555_result {
36 	unsigned int dst_pitch;
37 	const u16 expected[TEST_BUF_SIZE];
38 };
39 
40 struct convert_to_argb1555_result {
41 	unsigned int dst_pitch;
42 	const u16 expected[TEST_BUF_SIZE];
43 };
44 
45 struct convert_to_rgba5551_result {
46 	unsigned int dst_pitch;
47 	const u16 expected[TEST_BUF_SIZE];
48 };
49 
50 struct convert_to_rgb888_result {
51 	unsigned int dst_pitch;
52 	const u8 expected[TEST_BUF_SIZE];
53 };
54 
55 struct convert_to_argb8888_result {
56 	unsigned int dst_pitch;
57 	const u32 expected[TEST_BUF_SIZE];
58 };
59 
60 struct convert_to_xrgb2101010_result {
61 	unsigned int dst_pitch;
62 	const u32 expected[TEST_BUF_SIZE];
63 };
64 
65 struct convert_to_argb2101010_result {
66 	unsigned int dst_pitch;
67 	const u32 expected[TEST_BUF_SIZE];
68 };
69 
70 struct convert_to_mono_result {
71 	unsigned int dst_pitch;
72 	const u8 expected[TEST_BUF_SIZE];
73 };
74 
75 struct convert_xrgb8888_case {
76 	const char *name;
77 	unsigned int pitch;
78 	struct drm_rect clip;
79 	const u32 xrgb8888[TEST_BUF_SIZE];
80 	struct convert_to_gray8_result gray8_result;
81 	struct convert_to_rgb332_result rgb332_result;
82 	struct convert_to_rgb565_result rgb565_result;
83 	struct convert_to_xrgb1555_result xrgb1555_result;
84 	struct convert_to_argb1555_result argb1555_result;
85 	struct convert_to_rgba5551_result rgba5551_result;
86 	struct convert_to_rgb888_result rgb888_result;
87 	struct convert_to_argb8888_result argb8888_result;
88 	struct convert_to_xrgb2101010_result xrgb2101010_result;
89 	struct convert_to_argb2101010_result argb2101010_result;
90 	struct convert_to_mono_result mono_result;
91 };
92 
93 static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
94 	{
95 		.name = "single_pixel_source_buffer",
96 		.pitch = 1 * 4,
97 		.clip = DRM_RECT_INIT(0, 0, 1, 1),
98 		.xrgb8888 = { 0x01FF0000 },
99 		.gray8_result = {
100 			.dst_pitch = 0,
101 			.expected = { 0x4C },
102 		},
103 		.rgb332_result = {
104 			.dst_pitch = 0,
105 			.expected = { 0xE0 },
106 		},
107 		.rgb565_result = {
108 			.dst_pitch = 0,
109 			.expected = { 0xF800 },
110 			.expected_swab = { 0x00F8 },
111 		},
112 		.xrgb1555_result = {
113 			.dst_pitch = 0,
114 			.expected = { 0x7C00 },
115 		},
116 		.argb1555_result = {
117 			.dst_pitch = 0,
118 			.expected = { 0xFC00 },
119 		},
120 		.rgba5551_result = {
121 			.dst_pitch = 0,
122 			.expected = { 0xF801 },
123 		},
124 		.rgb888_result = {
125 			.dst_pitch = 0,
126 			.expected = { 0x00, 0x00, 0xFF },
127 		},
128 		.argb8888_result = {
129 			.dst_pitch = 0,
130 			.expected = { 0xFFFF0000 },
131 		},
132 		.xrgb2101010_result = {
133 			.dst_pitch = 0,
134 			.expected = { 0x3FF00000 },
135 		},
136 		.argb2101010_result = {
137 			.dst_pitch = 0,
138 			.expected = { 0xFFF00000 },
139 		},
140 		.mono_result = {
141 			.dst_pitch = 0,
142 			.expected = { 0b0 },
143 		},
144 	},
145 	{
146 		.name = "single_pixel_clip_rectangle",
147 		.pitch = 2 * 4,
148 		.clip = DRM_RECT_INIT(1, 1, 1, 1),
149 		.xrgb8888 = {
150 			0x00000000, 0x00000000,
151 			0x00000000, 0x10FF0000,
152 		},
153 		.gray8_result = {
154 			.dst_pitch = 0,
155 			.expected = { 0x4C },
156 		},
157 		.rgb332_result = {
158 			.dst_pitch = 0,
159 			.expected = { 0xE0 },
160 		},
161 		.rgb565_result = {
162 			.dst_pitch = 0,
163 			.expected = { 0xF800 },
164 			.expected_swab = { 0x00F8 },
165 		},
166 		.xrgb1555_result = {
167 			.dst_pitch = 0,
168 			.expected = { 0x7C00 },
169 		},
170 		.argb1555_result = {
171 			.dst_pitch = 0,
172 			.expected = { 0xFC00 },
173 		},
174 		.rgba5551_result = {
175 			.dst_pitch = 0,
176 			.expected = { 0xF801 },
177 		},
178 		.rgb888_result = {
179 			.dst_pitch = 0,
180 			.expected = { 0x00, 0x00, 0xFF },
181 		},
182 		.argb8888_result = {
183 			.dst_pitch = 0,
184 			.expected = { 0xFFFF0000 },
185 		},
186 		.xrgb2101010_result = {
187 			.dst_pitch = 0,
188 			.expected = { 0x3FF00000 },
189 		},
190 		.argb2101010_result = {
191 			.dst_pitch = 0,
192 			.expected = { 0xFFF00000 },
193 		},
194 		.mono_result = {
195 			.dst_pitch = 0,
196 			.expected = { 0b0 },
197 		},
198 	},
199 	{
200 		/* Well known colors: White, black, red, green, blue, magenta,
201 		 * yellow and cyan. Different values for the X in XRGB8888 to
202 		 * make sure it is ignored. Partial clip area.
203 		 */
204 		.name = "well_known_colors",
205 		.pitch = 4 * 4,
206 		.clip = DRM_RECT_INIT(1, 1, 2, 4),
207 		.xrgb8888 = {
208 			0x00000000, 0x00000000, 0x00000000, 0x00000000,
209 			0x00000000, 0x11FFFFFF, 0x22000000, 0x00000000,
210 			0x00000000, 0x33FF0000, 0x4400FF00, 0x00000000,
211 			0x00000000, 0x550000FF, 0x66FF00FF, 0x00000000,
212 			0x00000000, 0x77FFFF00, 0x8800FFFF, 0x00000000,
213 		},
214 		.gray8_result = {
215 			.dst_pitch = 0,
216 			.expected = {
217 				0xFF, 0x00,
218 				0x4C, 0x99,
219 				0x19, 0x66,
220 				0xE5, 0xB2,
221 			},
222 		},
223 		.rgb332_result = {
224 			.dst_pitch = 0,
225 			.expected = {
226 				0xFF, 0x00,
227 				0xE0, 0x1C,
228 				0x03, 0xE3,
229 				0xFC, 0x1F,
230 			},
231 		},
232 		.rgb565_result = {
233 			.dst_pitch = 0,
234 			.expected = {
235 				0xFFFF, 0x0000,
236 				0xF800, 0x07E0,
237 				0x001F, 0xF81F,
238 				0xFFE0, 0x07FF,
239 			},
240 			.expected_swab = {
241 				0xFFFF, 0x0000,
242 				0x00F8, 0xE007,
243 				0x1F00, 0x1FF8,
244 				0xE0FF, 0xFF07,
245 			},
246 		},
247 		.xrgb1555_result = {
248 			.dst_pitch = 0,
249 			.expected = {
250 				0x7FFF, 0x0000,
251 				0x7C00, 0x03E0,
252 				0x001F, 0x7C1F,
253 				0x7FE0, 0x03FF,
254 			},
255 		},
256 		.argb1555_result = {
257 			.dst_pitch = 0,
258 			.expected = {
259 				0xFFFF, 0x8000,
260 				0xFC00, 0x83E0,
261 				0x801F, 0xFC1F,
262 				0xFFE0, 0x83FF,
263 			},
264 		},
265 		.rgba5551_result = {
266 			.dst_pitch = 0,
267 			.expected = {
268 				0xFFFF, 0x0001,
269 				0xF801, 0x07C1,
270 				0x003F, 0xF83F,
271 				0xFFC1, 0x07FF,
272 			},
273 		},
274 		.rgb888_result = {
275 			.dst_pitch = 0,
276 			.expected = {
277 				0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
278 				0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00,
279 				0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF,
280 				0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
281 			},
282 		},
283 		.argb8888_result = {
284 			.dst_pitch = 0,
285 			.expected = {
286 				0xFFFFFFFF, 0xFF000000,
287 				0xFFFF0000, 0xFF00FF00,
288 				0xFF0000FF, 0xFFFF00FF,
289 				0xFFFFFF00, 0xFF00FFFF,
290 			},
291 		},
292 		.xrgb2101010_result = {
293 			.dst_pitch = 0,
294 			.expected = {
295 				0x3FFFFFFF, 0x00000000,
296 				0x3FF00000, 0x000FFC00,
297 				0x000003FF, 0x3FF003FF,
298 				0x3FFFFC00, 0x000FFFFF,
299 			},
300 		},
301 		.argb2101010_result = {
302 			.dst_pitch = 0,
303 			.expected = {
304 				0xFFFFFFFF, 0xC0000000,
305 				0xFFF00000, 0xC00FFC00,
306 				0xC00003FF, 0xFFF003FF,
307 				0xFFFFFC00, 0xC00FFFFF,
308 			},
309 		},
310 		.mono_result = {
311 			.dst_pitch = 0,
312 			.expected = {
313 				0b01,
314 				0b10,
315 				0b00,
316 				0b11,
317 			},
318 		},
319 	},
320 	{
321 		/* Randomly picked colors. Full buffer within the clip area. */
322 		.name = "destination_pitch",
323 		.pitch = 3 * 4,
324 		.clip = DRM_RECT_INIT(0, 0, 3, 3),
325 		.xrgb8888 = {
326 			0xA10E449C, 0xB1114D05, 0xC1A8F303,
327 			0xD16CF073, 0xA20E449C, 0xB2114D05,
328 			0xC2A80303, 0xD26CF073, 0xA30E449C,
329 		},
330 		.gray8_result = {
331 			.dst_pitch = 5,
332 			.expected = {
333 				0x3C, 0x33, 0xC4, 0x00, 0x00,
334 				0xBB, 0x3C, 0x33, 0x00, 0x00,
335 				0x34, 0xBB, 0x3C, 0x00, 0x00,
336 			},
337 		},
338 		.rgb332_result = {
339 			.dst_pitch = 5,
340 			.expected = {
341 				0x0A, 0x08, 0xBC, 0x00, 0x00,
342 				0x7D, 0x0A, 0x08, 0x00, 0x00,
343 				0xA0, 0x7D, 0x0A, 0x00, 0x00,
344 			},
345 		},
346 		.rgb565_result = {
347 			.dst_pitch = 10,
348 			.expected = {
349 				0x0A33, 0x1260, 0xAF80, 0x0000, 0x0000,
350 				0x6F8E, 0x0A33, 0x1260, 0x0000, 0x0000,
351 				0xA800, 0x6F8E, 0x0A33, 0x0000, 0x0000,
352 			},
353 			.expected_swab = {
354 				0x330A, 0x6012, 0x80AF, 0x0000, 0x0000,
355 				0x8E6F, 0x330A, 0x6012, 0x0000, 0x0000,
356 				0x00A8, 0x8E6F, 0x330A, 0x0000, 0x0000,
357 			},
358 		},
359 		.xrgb1555_result = {
360 			.dst_pitch = 10,
361 			.expected = {
362 				0x0513, 0x0920, 0x57C0, 0x0000, 0x0000,
363 				0x37CE, 0x0513, 0x0920, 0x0000, 0x0000,
364 				0x5400, 0x37CE, 0x0513, 0x0000, 0x0000,
365 			},
366 		},
367 		.argb1555_result = {
368 			.dst_pitch = 10,
369 			.expected = {
370 				0x8513, 0x8920, 0xD7C0, 0x0000, 0x0000,
371 				0xB7CE, 0x8513, 0x8920, 0x0000, 0x0000,
372 				0xD400, 0xB7CE, 0x8513, 0x0000, 0x0000,
373 			},
374 		},
375 		.rgba5551_result = {
376 			.dst_pitch = 10,
377 			.expected = {
378 				0x0A27, 0x1241, 0xAF81, 0x0000, 0x0000,
379 				0x6F9D, 0x0A27, 0x1241, 0x0000, 0x0000,
380 				0xA801, 0x6F9D, 0x0A27, 0x0000, 0x0000,
381 			},
382 		},
383 		.rgb888_result = {
384 			.dst_pitch = 15,
385 			.expected = {
386 				0x9C, 0x44, 0x0E, 0x05, 0x4D, 0x11, 0x03, 0xF3, 0xA8,
387 				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388 				0x73, 0xF0, 0x6C, 0x9C, 0x44, 0x0E, 0x05, 0x4D, 0x11,
389 				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
390 				0x03, 0x03, 0xA8, 0x73, 0xF0, 0x6C, 0x9C, 0x44, 0x0E,
391 				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 			},
393 		},
394 		.argb8888_result = {
395 			.dst_pitch = 20,
396 			.expected = {
397 				0xFF0E449C, 0xFF114D05, 0xFFA8F303, 0x00000000, 0x00000000,
398 				0xFF6CF073, 0xFF0E449C, 0xFF114D05, 0x00000000, 0x00000000,
399 				0xFFA80303, 0xFF6CF073, 0xFF0E449C, 0x00000000, 0x00000000,
400 			},
401 		},
402 		.xrgb2101010_result = {
403 			.dst_pitch = 20,
404 			.expected = {
405 				0x03844672, 0x0444D414, 0x2A2F3C0C, 0x00000000, 0x00000000,
406 				0x1B1F0DCD, 0x03844672, 0x0444D414, 0x00000000, 0x00000000,
407 				0x2A20300C, 0x1B1F0DCD, 0x03844672, 0x00000000, 0x00000000,
408 			},
409 		},
410 		.argb2101010_result = {
411 			.dst_pitch = 20,
412 			.expected = {
413 				0xC3844672, 0xC444D414, 0xEA2F3C0C, 0x00000000, 0x00000000,
414 				0xDB1F0DCD, 0xC3844672, 0xC444D414, 0x00000000, 0x00000000,
415 				0xEA20300C, 0xDB1F0DCD, 0xC3844672, 0x00000000, 0x00000000,
416 			},
417 		},
418 		.mono_result = {
419 			.dst_pitch = 2,
420 			.expected = {
421 				0b100, 0b000,
422 				0b001, 0b000,
423 				0b010, 0b000,
424 			},
425 		},
426 	},
427 };
428 
429 /*
430  * conversion_buf_size - Return the destination buffer size required to convert
431  * between formats.
432  * @dst_format: destination buffer pixel format (DRM_FORMAT_*)
433  * @dst_pitch: Number of bytes between two consecutive scanlines within dst
434  * @clip: Clip rectangle area to convert
435  *
436  * Returns:
437  * The size of the destination buffer or negative value on error.
438  */
439 static size_t conversion_buf_size(u32 dst_format, unsigned int dst_pitch,
440 				  const struct drm_rect *clip)
441 {
442 	const struct drm_format_info *dst_fi = drm_format_info(dst_format);
443 
444 	if (!dst_fi)
445 		return -EINVAL;
446 
447 	if (!dst_pitch)
448 		dst_pitch = drm_format_info_min_pitch(dst_fi, 0, drm_rect_width(clip));
449 
450 	return dst_pitch * drm_rect_height(clip);
451 }
452 
453 static u16 *le16buf_to_cpu(struct kunit *test, const __le16 *buf, size_t buf_size)
454 {
455 	u16 *dst = NULL;
456 	int n;
457 
458 	dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL);
459 	if (!dst)
460 		return NULL;
461 
462 	for (n = 0; n < buf_size; n++)
463 		dst[n] = le16_to_cpu(buf[n]);
464 
465 	return dst;
466 }
467 
468 static u32 *le32buf_to_cpu(struct kunit *test, const __le32 *buf, size_t buf_size)
469 {
470 	u32 *dst = NULL;
471 	int n;
472 
473 	dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL);
474 	if (!dst)
475 		return NULL;
476 
477 	for (n = 0; n < buf_size; n++)
478 		dst[n] = le32_to_cpu((__force __le32)buf[n]);
479 
480 	return dst;
481 }
482 
483 static __le32 *cpubuf_to_le32(struct kunit *test, const u32 *buf, size_t buf_size)
484 {
485 	__le32 *dst = NULL;
486 	int n;
487 
488 	dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL);
489 	if (!dst)
490 		return NULL;
491 
492 	for (n = 0; n < buf_size; n++)
493 		dst[n] = cpu_to_le32(buf[n]);
494 
495 	return dst;
496 }
497 
498 static void convert_xrgb8888_case_desc(struct convert_xrgb8888_case *t,
499 				       char *desc)
500 {
501 	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
502 }
503 
504 KUNIT_ARRAY_PARAM(convert_xrgb8888, convert_xrgb8888_cases,
505 		  convert_xrgb8888_case_desc);
506 
507 static void drm_test_fb_xrgb8888_to_gray8(struct kunit *test)
508 {
509 	const struct convert_xrgb8888_case *params = test->param_value;
510 	const struct convert_to_gray8_result *result = &params->gray8_result;
511 	size_t dst_size;
512 	u8 *buf = NULL;
513 	__le32 *xrgb8888 = NULL;
514 	struct iosys_map dst, src;
515 
516 	struct drm_framebuffer fb = {
517 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
518 		.pitches = { params->pitch, 0, 0 },
519 	};
520 
521 	dst_size = conversion_buf_size(DRM_FORMAT_R8, result->dst_pitch,
522 				       &params->clip);
523 	KUNIT_ASSERT_GT(test, dst_size, 0);
524 
525 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
526 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
527 	iosys_map_set_vaddr(&dst, buf);
528 
529 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
530 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
531 	iosys_map_set_vaddr(&src, xrgb8888);
532 
533 	drm_fb_xrgb8888_to_gray8(&dst, &result->dst_pitch, &src, &fb, &params->clip);
534 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
535 }
536 
537 static void drm_test_fb_xrgb8888_to_rgb332(struct kunit *test)
538 {
539 	const struct convert_xrgb8888_case *params = test->param_value;
540 	const struct convert_to_rgb332_result *result = &params->rgb332_result;
541 	size_t dst_size;
542 	u8 *buf = NULL;
543 	__le32 *xrgb8888 = NULL;
544 	struct iosys_map dst, src;
545 
546 	struct drm_framebuffer fb = {
547 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
548 		.pitches = { params->pitch, 0, 0 },
549 	};
550 
551 	dst_size = conversion_buf_size(DRM_FORMAT_RGB332, result->dst_pitch,
552 				       &params->clip);
553 	KUNIT_ASSERT_GT(test, dst_size, 0);
554 
555 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
556 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
557 	iosys_map_set_vaddr(&dst, buf);
558 
559 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
560 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
561 	iosys_map_set_vaddr(&src, xrgb8888);
562 
563 	drm_fb_xrgb8888_to_rgb332(&dst, &result->dst_pitch, &src, &fb, &params->clip);
564 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
565 }
566 
567 static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test)
568 {
569 	const struct convert_xrgb8888_case *params = test->param_value;
570 	const struct convert_to_rgb565_result *result = &params->rgb565_result;
571 	size_t dst_size;
572 	u16 *buf = NULL;
573 	__le32 *xrgb8888 = NULL;
574 	struct iosys_map dst, src;
575 
576 	struct drm_framebuffer fb = {
577 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
578 		.pitches = { params->pitch, 0, 0 },
579 	};
580 
581 	dst_size = conversion_buf_size(DRM_FORMAT_RGB565, result->dst_pitch,
582 				       &params->clip);
583 	KUNIT_ASSERT_GT(test, dst_size, 0);
584 
585 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
586 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
587 	iosys_map_set_vaddr(&dst, buf);
588 
589 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
590 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
591 	iosys_map_set_vaddr(&src, xrgb8888);
592 
593 	drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, false);
594 	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
595 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
596 
597 	buf = dst.vaddr; /* restore original value of buf */
598 	drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, true);
599 	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
600 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected_swab, dst_size);
601 }
602 
603 static void drm_test_fb_xrgb8888_to_xrgb1555(struct kunit *test)
604 {
605 	const struct convert_xrgb8888_case *params = test->param_value;
606 	const struct convert_to_xrgb1555_result *result = &params->xrgb1555_result;
607 	size_t dst_size;
608 	u16 *buf = NULL;
609 	__le32 *xrgb8888 = NULL;
610 	struct iosys_map dst, src;
611 
612 	struct drm_framebuffer fb = {
613 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
614 		.pitches = { params->pitch, 0, 0 },
615 	};
616 
617 	dst_size = conversion_buf_size(DRM_FORMAT_XRGB1555, result->dst_pitch,
618 				       &params->clip);
619 	KUNIT_ASSERT_GT(test, dst_size, 0);
620 
621 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
622 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
623 	iosys_map_set_vaddr(&dst, buf);
624 
625 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
626 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
627 	iosys_map_set_vaddr(&src, xrgb8888);
628 
629 	drm_fb_xrgb8888_to_xrgb1555(&dst, &result->dst_pitch, &src, &fb, &params->clip);
630 	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
631 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
632 }
633 
634 static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test)
635 {
636 	const struct convert_xrgb8888_case *params = test->param_value;
637 	const struct convert_to_argb1555_result *result = &params->argb1555_result;
638 	size_t dst_size;
639 	u16 *buf = NULL;
640 	__le32 *xrgb8888 = NULL;
641 	struct iosys_map dst, src;
642 
643 	struct drm_framebuffer fb = {
644 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
645 		.pitches = { params->pitch, 0, 0 },
646 	};
647 
648 	dst_size = conversion_buf_size(DRM_FORMAT_ARGB1555, result->dst_pitch,
649 				       &params->clip);
650 	KUNIT_ASSERT_GT(test, dst_size, 0);
651 
652 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
653 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
654 	iosys_map_set_vaddr(&dst, buf);
655 
656 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
657 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
658 	iosys_map_set_vaddr(&src, xrgb8888);
659 
660 	drm_fb_xrgb8888_to_argb1555(&dst, &result->dst_pitch, &src, &fb, &params->clip);
661 	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
662 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
663 }
664 
665 static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test)
666 {
667 	const struct convert_xrgb8888_case *params = test->param_value;
668 	const struct convert_to_rgba5551_result *result = &params->rgba5551_result;
669 	size_t dst_size;
670 	u16 *buf = NULL;
671 	__le32 *xrgb8888 = NULL;
672 	struct iosys_map dst, src;
673 
674 	struct drm_framebuffer fb = {
675 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
676 		.pitches = { params->pitch, 0, 0 },
677 	};
678 
679 	dst_size = conversion_buf_size(DRM_FORMAT_RGBA5551, result->dst_pitch,
680 				       &params->clip);
681 	KUNIT_ASSERT_GT(test, dst_size, 0);
682 
683 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
684 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
685 	iosys_map_set_vaddr(&dst, buf);
686 
687 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
688 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
689 	iosys_map_set_vaddr(&src, xrgb8888);
690 
691 	drm_fb_xrgb8888_to_rgba5551(&dst, &result->dst_pitch, &src, &fb, &params->clip);
692 	buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16));
693 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
694 }
695 
696 static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)
697 {
698 	const struct convert_xrgb8888_case *params = test->param_value;
699 	const struct convert_to_rgb888_result *result = &params->rgb888_result;
700 	size_t dst_size;
701 	u8 *buf = NULL;
702 	__le32 *xrgb8888 = NULL;
703 	struct iosys_map dst, src;
704 
705 	struct drm_framebuffer fb = {
706 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
707 		.pitches = { params->pitch, 0, 0 },
708 	};
709 
710 	dst_size = conversion_buf_size(DRM_FORMAT_RGB888, result->dst_pitch,
711 				       &params->clip);
712 	KUNIT_ASSERT_GT(test, dst_size, 0);
713 
714 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
715 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
716 	iosys_map_set_vaddr(&dst, buf);
717 
718 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
719 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
720 	iosys_map_set_vaddr(&src, xrgb8888);
721 
722 	/*
723 	 * RGB888 expected results are already in little-endian
724 	 * order, so there's no need to convert the test output.
725 	 */
726 	drm_fb_xrgb8888_to_rgb888(&dst, &result->dst_pitch, &src, &fb, &params->clip);
727 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
728 }
729 
730 static void drm_test_fb_xrgb8888_to_argb8888(struct kunit *test)
731 {
732 	const struct convert_xrgb8888_case *params = test->param_value;
733 	const struct convert_to_argb8888_result *result = &params->argb8888_result;
734 	size_t dst_size;
735 	u32 *buf = NULL;
736 	__le32 *xrgb8888 = NULL;
737 	struct iosys_map dst, src;
738 
739 	struct drm_framebuffer fb = {
740 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
741 		.pitches = { params->pitch, 0, 0 },
742 	};
743 
744 	dst_size = conversion_buf_size(DRM_FORMAT_ARGB8888,
745 				       result->dst_pitch, &params->clip);
746 	KUNIT_ASSERT_GT(test, dst_size, 0);
747 
748 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
749 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
750 	iosys_map_set_vaddr(&dst, buf);
751 
752 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
753 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
754 	iosys_map_set_vaddr(&src, xrgb8888);
755 
756 	drm_fb_xrgb8888_to_argb8888(&dst, &result->dst_pitch, &src, &fb, &params->clip);
757 	buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));
758 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
759 }
760 
761 static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)
762 {
763 	const struct convert_xrgb8888_case *params = test->param_value;
764 	const struct convert_to_xrgb2101010_result *result = &params->xrgb2101010_result;
765 	size_t dst_size;
766 	u32 *buf = NULL;
767 	__le32 *xrgb8888 = NULL;
768 	struct iosys_map dst, src;
769 
770 	struct drm_framebuffer fb = {
771 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
772 		.pitches = { params->pitch, 0, 0 },
773 	};
774 
775 	dst_size = conversion_buf_size(DRM_FORMAT_XRGB2101010,
776 				       result->dst_pitch, &params->clip);
777 	KUNIT_ASSERT_GT(test, dst_size, 0);
778 
779 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
780 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
781 	iosys_map_set_vaddr(&dst, buf);
782 
783 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
784 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
785 	iosys_map_set_vaddr(&src, xrgb8888);
786 
787 	drm_fb_xrgb8888_to_xrgb2101010(&dst, &result->dst_pitch, &src, &fb, &params->clip);
788 	buf = le32buf_to_cpu(test, buf, dst_size / sizeof(u32));
789 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
790 }
791 
792 static void drm_test_fb_xrgb8888_to_argb2101010(struct kunit *test)
793 {
794 	const struct convert_xrgb8888_case *params = test->param_value;
795 	const struct convert_to_argb2101010_result *result = &params->argb2101010_result;
796 	size_t dst_size;
797 	u32 *buf = NULL;
798 	__le32 *xrgb8888 = NULL;
799 	struct iosys_map dst, src;
800 
801 	struct drm_framebuffer fb = {
802 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
803 		.pitches = { params->pitch, 0, 0 },
804 	};
805 
806 	dst_size = conversion_buf_size(DRM_FORMAT_ARGB2101010,
807 				       result->dst_pitch, &params->clip);
808 	KUNIT_ASSERT_GT(test, dst_size, 0);
809 
810 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
811 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
812 	iosys_map_set_vaddr(&dst, buf);
813 
814 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
815 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
816 	iosys_map_set_vaddr(&src, xrgb8888);
817 
818 	drm_fb_xrgb8888_to_argb2101010(&dst, &result->dst_pitch, &src, &fb, &params->clip);
819 	buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32));
820 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
821 }
822 
823 static void drm_test_fb_xrgb8888_to_mono(struct kunit *test)
824 {
825 	const struct convert_xrgb8888_case *params = test->param_value;
826 	const struct convert_to_mono_result *result = &params->mono_result;
827 	size_t dst_size;
828 	u8 *buf = NULL;
829 	__le32 *xrgb8888 = NULL;
830 	struct iosys_map dst, src;
831 
832 	struct drm_framebuffer fb = {
833 		.format = drm_format_info(DRM_FORMAT_XRGB8888),
834 		.pitches = { params->pitch, 0, 0 },
835 	};
836 
837 	dst_size = conversion_buf_size(DRM_FORMAT_C1, result->dst_pitch, &params->clip);
838 
839 	KUNIT_ASSERT_GT(test, dst_size, 0);
840 
841 	buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
842 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
843 	iosys_map_set_vaddr(&dst, buf);
844 
845 	xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
846 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
847 	iosys_map_set_vaddr(&src, xrgb8888);
848 
849 	drm_fb_xrgb8888_to_mono(&dst, &result->dst_pitch, &src, &fb, &params->clip);
850 	KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
851 }
852 
853 static struct kunit_case drm_format_helper_test_cases[] = {
854 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_gray8, convert_xrgb8888_gen_params),
855 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb332, convert_xrgb8888_gen_params),
856 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb565, convert_xrgb8888_gen_params),
857 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb1555, convert_xrgb8888_gen_params),
858 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb1555, convert_xrgb8888_gen_params),
859 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgba5551, convert_xrgb8888_gen_params),
860 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb888, convert_xrgb8888_gen_params),
861 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb8888, convert_xrgb8888_gen_params),
862 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb2101010, convert_xrgb8888_gen_params),
863 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb2101010, convert_xrgb8888_gen_params),
864 	KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_mono, convert_xrgb8888_gen_params),
865 	{}
866 };
867 
868 static struct kunit_suite drm_format_helper_test_suite = {
869 	.name = "drm_format_helper_test",
870 	.test_cases = drm_format_helper_test_cases,
871 };
872 
873 kunit_test_suite(drm_format_helper_test_suite);
874 
875 MODULE_DESCRIPTION("KUnit tests for the drm_format_helper APIs");
876 MODULE_LICENSE("GPL");
877 MODULE_AUTHOR("José Expósito <jose.exposito89@gmail.com>");
878