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 = ¶ms->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 ¶ms->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, ¶ms->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 = ¶ms->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 ¶ms->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, ¶ms->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 = ¶ms->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 ¶ms->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, ¶ms->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, ¶ms->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 = ¶ms->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 ¶ms->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, ¶ms->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 = ¶ms->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 ¶ms->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, ¶ms->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 = ¶ms->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 ¶ms->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, ¶ms->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 = ¶ms->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 ¶ms->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, ¶ms->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 = ¶ms->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, ¶ms->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, ¶ms->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 = ¶ms->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, ¶ms->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, ¶ms->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 = ¶ms->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, ¶ms->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, ¶ms->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 = ¶ms->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, ¶ms->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, ¶ms->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 = ¶ms->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, ¶ms->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, ¶ms->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(¶ms->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, ¶ms->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 ¶ms->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, ¶ms->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