1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Kunit test for drm_modes functions 4 */ 5 6 #include <linux/i2c.h> 7 8 #include <drm/drm_atomic_state_helper.h> 9 #include <drm/drm_connector.h> 10 #include <drm/drm_drv.h> 11 #include <drm/drm_edid.h> 12 #include <drm/drm_kunit_helpers.h> 13 #include <drm/drm_modes.h> 14 15 #include <drm/display/drm_hdmi_helper.h> 16 17 #include <kunit/test.h> 18 19 #include "../drm_crtc_internal.h" 20 21 struct drm_connector_init_priv { 22 struct drm_device drm; 23 struct drm_connector connector; 24 struct i2c_adapter ddc; 25 }; 26 27 static const struct drm_connector_hdmi_funcs dummy_hdmi_funcs = { 28 }; 29 30 static const struct drm_connector_funcs dummy_funcs = { 31 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 32 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 33 .reset = drm_atomic_helper_connector_reset, 34 }; 35 36 static int dummy_ddc_xfer(struct i2c_adapter *adapter, 37 struct i2c_msg *msgs, int num) 38 { 39 return num; 40 } 41 42 static u32 dummy_ddc_func(struct i2c_adapter *adapter) 43 { 44 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 45 } 46 47 static const struct i2c_algorithm dummy_ddc_algorithm = { 48 .master_xfer = dummy_ddc_xfer, 49 .functionality = dummy_ddc_func, 50 }; 51 52 static void i2c_del_adapter_wrapper(void *ptr) 53 { 54 struct i2c_adapter *adap = ptr; 55 56 i2c_del_adapter(adap); 57 } 58 59 static int drm_test_connector_init(struct kunit *test) 60 { 61 struct drm_connector_init_priv *priv; 62 struct device *dev; 63 int ret; 64 65 dev = drm_kunit_helper_alloc_device(test); 66 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); 67 68 priv = drm_kunit_helper_alloc_drm_device(test, dev, 69 struct drm_connector_init_priv, drm, 70 DRIVER_MODESET | DRIVER_ATOMIC); 71 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 72 73 strscpy(priv->ddc.name, "dummy-connector-ddc", sizeof(priv->ddc.name)); 74 priv->ddc.owner = THIS_MODULE; 75 priv->ddc.algo = &dummy_ddc_algorithm; 76 priv->ddc.dev.parent = dev; 77 78 ret = i2c_add_adapter(&priv->ddc); 79 KUNIT_ASSERT_EQ(test, ret, 0); 80 81 ret = kunit_add_action_or_reset(test, i2c_del_adapter_wrapper, &priv->ddc); 82 KUNIT_ASSERT_EQ(test, ret, 0); 83 84 test->priv = priv; 85 return 0; 86 } 87 88 /* 89 * Test that the registration of a bog standard connector works as 90 * expected and doesn't report any error. 91 */ 92 static void drm_test_drmm_connector_init(struct kunit *test) 93 { 94 struct drm_connector_init_priv *priv = test->priv; 95 int ret; 96 97 ret = drmm_connector_init(&priv->drm, &priv->connector, 98 &dummy_funcs, 99 DRM_MODE_CONNECTOR_HDMIA, 100 &priv->ddc); 101 KUNIT_EXPECT_EQ(test, ret, 0); 102 } 103 104 /* 105 * Test that the registration of a connector without a DDC adapter 106 * doesn't report any error. 107 */ 108 static void drm_test_drmm_connector_init_null_ddc(struct kunit *test) 109 { 110 struct drm_connector_init_priv *priv = test->priv; 111 int ret; 112 113 ret = drmm_connector_init(&priv->drm, &priv->connector, 114 &dummy_funcs, 115 DRM_MODE_CONNECTOR_HDMIA, 116 NULL); 117 KUNIT_EXPECT_EQ(test, ret, 0); 118 } 119 120 /* 121 * Test that the registration of a connector succeeds for all possible 122 * connector types. 123 */ 124 static void drm_test_drmm_connector_init_type_valid(struct kunit *test) 125 { 126 struct drm_connector_init_priv *priv = test->priv; 127 unsigned int connector_type = *(unsigned int *)test->param_value; 128 int ret; 129 130 ret = drmm_connector_init(&priv->drm, &priv->connector, 131 &dummy_funcs, 132 connector_type, 133 &priv->ddc); 134 KUNIT_EXPECT_EQ(test, ret, 0); 135 } 136 137 static const unsigned int drm_connector_init_type_valid_tests[] = { 138 DRM_MODE_CONNECTOR_Unknown, 139 DRM_MODE_CONNECTOR_VGA, 140 DRM_MODE_CONNECTOR_DVII, 141 DRM_MODE_CONNECTOR_DVID, 142 DRM_MODE_CONNECTOR_DVIA, 143 DRM_MODE_CONNECTOR_Composite, 144 DRM_MODE_CONNECTOR_SVIDEO, 145 DRM_MODE_CONNECTOR_LVDS, 146 DRM_MODE_CONNECTOR_Component, 147 DRM_MODE_CONNECTOR_9PinDIN, 148 DRM_MODE_CONNECTOR_DisplayPort, 149 DRM_MODE_CONNECTOR_HDMIA, 150 DRM_MODE_CONNECTOR_HDMIB, 151 DRM_MODE_CONNECTOR_TV, 152 DRM_MODE_CONNECTOR_eDP, 153 DRM_MODE_CONNECTOR_VIRTUAL, 154 DRM_MODE_CONNECTOR_DSI, 155 DRM_MODE_CONNECTOR_DPI, 156 DRM_MODE_CONNECTOR_WRITEBACK, 157 DRM_MODE_CONNECTOR_SPI, 158 DRM_MODE_CONNECTOR_USB, 159 }; 160 161 static void drm_connector_init_type_desc(const unsigned int *type, char *desc) 162 { 163 sprintf(desc, "%s", drm_get_connector_type_name(*type)); 164 } 165 166 KUNIT_ARRAY_PARAM(drm_connector_init_type_valid, 167 drm_connector_init_type_valid_tests, 168 drm_connector_init_type_desc); 169 170 static struct kunit_case drmm_connector_init_tests[] = { 171 KUNIT_CASE(drm_test_drmm_connector_init), 172 KUNIT_CASE(drm_test_drmm_connector_init_null_ddc), 173 KUNIT_CASE_PARAM(drm_test_drmm_connector_init_type_valid, 174 drm_connector_init_type_valid_gen_params), 175 { } 176 }; 177 178 static struct kunit_suite drmm_connector_init_test_suite = { 179 .name = "drmm_connector_init", 180 .init = drm_test_connector_init, 181 .test_cases = drmm_connector_init_tests, 182 }; 183 184 /* 185 * Test that the registration of a bog standard connector works as 186 * expected and doesn't report any error. 187 */ 188 static void drm_test_connector_hdmi_init_valid(struct kunit *test) 189 { 190 struct drm_connector_init_priv *priv = test->priv; 191 int ret; 192 193 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 194 "Vendor", "Product", 195 &dummy_funcs, 196 &dummy_hdmi_funcs, 197 DRM_MODE_CONNECTOR_HDMIA, 198 &priv->ddc, 199 BIT(HDMI_COLORSPACE_RGB), 200 8); 201 KUNIT_EXPECT_EQ(test, ret, 0); 202 } 203 204 /* 205 * Test that the registration of a connector without a DDC adapter 206 * doesn't report any error. 207 */ 208 static void drm_test_connector_hdmi_init_null_ddc(struct kunit *test) 209 { 210 struct drm_connector_init_priv *priv = test->priv; 211 int ret; 212 213 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 214 "Vendor", "Product", 215 &dummy_funcs, 216 &dummy_hdmi_funcs, 217 DRM_MODE_CONNECTOR_HDMIA, 218 NULL, 219 BIT(HDMI_COLORSPACE_RGB), 220 8); 221 KUNIT_EXPECT_EQ(test, ret, 0); 222 } 223 224 /* 225 * Test that the registration of a connector with an invalid maximum bpc 226 * count fails. 227 */ 228 static void drm_test_connector_hdmi_init_bpc_invalid(struct kunit *test) 229 { 230 struct drm_connector_init_priv *priv = test->priv; 231 int ret; 232 233 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 234 "Vendor", "Product", 235 &dummy_funcs, 236 &dummy_hdmi_funcs, 237 DRM_MODE_CONNECTOR_HDMIA, 238 &priv->ddc, 239 BIT(HDMI_COLORSPACE_RGB), 240 9); 241 KUNIT_EXPECT_LT(test, ret, 0); 242 } 243 244 /* 245 * Test that the registration of a connector with a null maximum bpc 246 * count fails. 247 */ 248 static void drm_test_connector_hdmi_init_bpc_null(struct kunit *test) 249 { 250 struct drm_connector_init_priv *priv = test->priv; 251 int ret; 252 253 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 254 "Vendor", "Product", 255 &dummy_funcs, 256 &dummy_hdmi_funcs, 257 DRM_MODE_CONNECTOR_HDMIA, 258 &priv->ddc, 259 BIT(HDMI_COLORSPACE_RGB), 260 0); 261 KUNIT_EXPECT_LT(test, ret, 0); 262 } 263 264 /* 265 * Test that the registration of a connector with a maximum bpc count of 266 * 8 succeeds, registers the max bpc property, but doesn't register the 267 * HDR output metadata one. 268 */ 269 static void drm_test_connector_hdmi_init_bpc_8(struct kunit *test) 270 { 271 struct drm_connector_init_priv *priv = test->priv; 272 struct drm_connector_state *state; 273 struct drm_connector *connector = &priv->connector; 274 struct drm_property *prop; 275 uint64_t val; 276 int ret; 277 278 ret = drmm_connector_hdmi_init(&priv->drm, connector, 279 "Vendor", "Product", 280 &dummy_funcs, 281 &dummy_hdmi_funcs, 282 DRM_MODE_CONNECTOR_HDMIA, 283 &priv->ddc, 284 BIT(HDMI_COLORSPACE_RGB), 285 8); 286 KUNIT_EXPECT_EQ(test, ret, 0); 287 288 prop = connector->max_bpc_property; 289 KUNIT_ASSERT_NOT_NULL(test, prop); 290 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); 291 292 ret = drm_object_property_get_default_value(&connector->base, prop, &val); 293 KUNIT_EXPECT_EQ(test, ret, 0); 294 KUNIT_EXPECT_EQ(test, val, 8); 295 296 state = connector->state; 297 KUNIT_EXPECT_EQ(test, state->max_bpc, 8); 298 KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 8); 299 300 prop = priv->drm.mode_config.hdr_output_metadata_property; 301 KUNIT_ASSERT_NOT_NULL(test, prop); 302 KUNIT_EXPECT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); 303 } 304 305 /* 306 * Test that the registration of a connector with a maximum bpc count of 307 * 10 succeeds and registers the max bpc and HDR output metadata 308 * properties. 309 */ 310 static void drm_test_connector_hdmi_init_bpc_10(struct kunit *test) 311 { 312 struct drm_connector_init_priv *priv = test->priv; 313 struct drm_connector_state *state; 314 struct drm_connector *connector = &priv->connector; 315 struct drm_property *prop; 316 uint64_t val; 317 int ret; 318 319 ret = drmm_connector_hdmi_init(&priv->drm, connector, 320 "Vendor", "Product", 321 &dummy_funcs, 322 &dummy_hdmi_funcs, 323 DRM_MODE_CONNECTOR_HDMIA, 324 &priv->ddc, 325 BIT(HDMI_COLORSPACE_RGB), 326 10); 327 KUNIT_EXPECT_EQ(test, ret, 0); 328 329 prop = connector->max_bpc_property; 330 KUNIT_ASSERT_NOT_NULL(test, prop); 331 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); 332 333 ret = drm_object_property_get_default_value(&connector->base, prop, &val); 334 KUNIT_EXPECT_EQ(test, ret, 0); 335 KUNIT_EXPECT_EQ(test, val, 10); 336 337 state = connector->state; 338 KUNIT_EXPECT_EQ(test, state->max_bpc, 10); 339 KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 10); 340 341 prop = priv->drm.mode_config.hdr_output_metadata_property; 342 KUNIT_ASSERT_NOT_NULL(test, prop); 343 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); 344 } 345 346 /* 347 * Test that the registration of a connector with a maximum bpc count of 348 * 12 succeeds and registers the max bpc and HDR output metadata 349 * properties. 350 */ 351 static void drm_test_connector_hdmi_init_bpc_12(struct kunit *test) 352 { 353 struct drm_connector_init_priv *priv = test->priv; 354 struct drm_connector_state *state; 355 struct drm_connector *connector = &priv->connector; 356 struct drm_property *prop; 357 uint64_t val; 358 int ret; 359 360 ret = drmm_connector_hdmi_init(&priv->drm, connector, 361 "Vendor", "Product", 362 &dummy_funcs, 363 &dummy_hdmi_funcs, 364 DRM_MODE_CONNECTOR_HDMIA, 365 &priv->ddc, 366 BIT(HDMI_COLORSPACE_RGB), 367 12); 368 KUNIT_EXPECT_EQ(test, ret, 0); 369 370 prop = connector->max_bpc_property; 371 KUNIT_ASSERT_NOT_NULL(test, prop); 372 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); 373 374 ret = drm_object_property_get_default_value(&connector->base, prop, &val); 375 KUNIT_EXPECT_EQ(test, ret, 0); 376 KUNIT_EXPECT_EQ(test, val, 12); 377 378 state = connector->state; 379 KUNIT_EXPECT_EQ(test, state->max_bpc, 12); 380 KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 12); 381 382 prop = priv->drm.mode_config.hdr_output_metadata_property; 383 KUNIT_ASSERT_NOT_NULL(test, prop); 384 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); 385 } 386 387 /* 388 * Test that the registration of an HDMI connector with no supported 389 * format fails. 390 */ 391 static void drm_test_connector_hdmi_init_formats_empty(struct kunit *test) 392 { 393 struct drm_connector_init_priv *priv = test->priv; 394 int ret; 395 396 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 397 "Vendor", "Product", 398 &dummy_funcs, 399 &dummy_hdmi_funcs, 400 DRM_MODE_CONNECTOR_HDMIA, 401 &priv->ddc, 402 0, 403 8); 404 KUNIT_EXPECT_LT(test, ret, 0); 405 } 406 407 /* 408 * Test that the registration of an HDMI connector not listing RGB as a 409 * supported format fails. 410 */ 411 static void drm_test_connector_hdmi_init_formats_no_rgb(struct kunit *test) 412 { 413 struct drm_connector_init_priv *priv = test->priv; 414 int ret; 415 416 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 417 "Vendor", "Product", 418 &dummy_funcs, 419 &dummy_hdmi_funcs, 420 DRM_MODE_CONNECTOR_HDMIA, 421 &priv->ddc, 422 BIT(HDMI_COLORSPACE_YUV422), 423 8); 424 KUNIT_EXPECT_LT(test, ret, 0); 425 } 426 427 /* 428 * Test that the registration of an HDMI connector with an HDMI 429 * connector type succeeds. 430 */ 431 static void drm_test_connector_hdmi_init_type_valid(struct kunit *test) 432 { 433 struct drm_connector_init_priv *priv = test->priv; 434 unsigned int connector_type = *(unsigned int *)test->param_value; 435 int ret; 436 437 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 438 "Vendor", "Product", 439 &dummy_funcs, 440 &dummy_hdmi_funcs, 441 connector_type, 442 &priv->ddc, 443 BIT(HDMI_COLORSPACE_RGB), 444 8); 445 KUNIT_EXPECT_EQ(test, ret, 0); 446 } 447 448 static const unsigned int drm_connector_hdmi_init_type_valid_tests[] = { 449 DRM_MODE_CONNECTOR_HDMIA, 450 DRM_MODE_CONNECTOR_HDMIB, 451 }; 452 453 static void drm_connector_hdmi_init_type_desc(const unsigned int *type, char *desc) 454 { 455 sprintf(desc, "%s", drm_get_connector_type_name(*type)); 456 } 457 458 KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_valid, 459 drm_connector_hdmi_init_type_valid_tests, 460 drm_connector_hdmi_init_type_desc); 461 462 /* 463 * Test that the registration of an HDMI connector with an !HDMI 464 * connector type fails. 465 */ 466 static void drm_test_connector_hdmi_init_type_invalid(struct kunit *test) 467 { 468 struct drm_connector_init_priv *priv = test->priv; 469 unsigned int connector_type = *(unsigned int *)test->param_value; 470 int ret; 471 472 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector, 473 "Vendor", "Product", 474 &dummy_funcs, 475 &dummy_hdmi_funcs, 476 connector_type, 477 &priv->ddc, 478 BIT(HDMI_COLORSPACE_RGB), 479 8); 480 KUNIT_EXPECT_LT(test, ret, 0); 481 } 482 483 static const unsigned int drm_connector_hdmi_init_type_invalid_tests[] = { 484 DRM_MODE_CONNECTOR_Unknown, 485 DRM_MODE_CONNECTOR_VGA, 486 DRM_MODE_CONNECTOR_DVII, 487 DRM_MODE_CONNECTOR_DVID, 488 DRM_MODE_CONNECTOR_DVIA, 489 DRM_MODE_CONNECTOR_Composite, 490 DRM_MODE_CONNECTOR_SVIDEO, 491 DRM_MODE_CONNECTOR_LVDS, 492 DRM_MODE_CONNECTOR_Component, 493 DRM_MODE_CONNECTOR_9PinDIN, 494 DRM_MODE_CONNECTOR_DisplayPort, 495 DRM_MODE_CONNECTOR_TV, 496 DRM_MODE_CONNECTOR_eDP, 497 DRM_MODE_CONNECTOR_VIRTUAL, 498 DRM_MODE_CONNECTOR_DSI, 499 DRM_MODE_CONNECTOR_DPI, 500 DRM_MODE_CONNECTOR_WRITEBACK, 501 DRM_MODE_CONNECTOR_SPI, 502 DRM_MODE_CONNECTOR_USB, 503 }; 504 505 KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_invalid, 506 drm_connector_hdmi_init_type_invalid_tests, 507 drm_connector_hdmi_init_type_desc); 508 509 static struct kunit_case drmm_connector_hdmi_init_tests[] = { 510 KUNIT_CASE(drm_test_connector_hdmi_init_valid), 511 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_8), 512 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_10), 513 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_12), 514 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_invalid), 515 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_null), 516 KUNIT_CASE(drm_test_connector_hdmi_init_formats_empty), 517 KUNIT_CASE(drm_test_connector_hdmi_init_formats_no_rgb), 518 KUNIT_CASE(drm_test_connector_hdmi_init_null_ddc), 519 KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_valid, 520 drm_connector_hdmi_init_type_valid_gen_params), 521 KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_invalid, 522 drm_connector_hdmi_init_type_invalid_gen_params), 523 { } 524 }; 525 526 static struct kunit_suite drmm_connector_hdmi_init_test_suite = { 527 .name = "drmm_connector_hdmi_init", 528 .init = drm_test_connector_init, 529 .test_cases = drmm_connector_hdmi_init_tests, 530 }; 531 532 struct drm_get_tv_mode_from_name_test { 533 const char *name; 534 enum drm_connector_tv_mode expected_mode; 535 }; 536 537 #define TV_MODE_NAME(_name, _mode) \ 538 { \ 539 .name = _name, \ 540 .expected_mode = _mode, \ 541 } 542 543 static void drm_test_get_tv_mode_from_name_valid(struct kunit *test) 544 { 545 const struct drm_get_tv_mode_from_name_test *params = test->param_value; 546 547 KUNIT_EXPECT_EQ(test, 548 drm_get_tv_mode_from_name(params->name, strlen(params->name)), 549 params->expected_mode); 550 } 551 552 static const 553 struct drm_get_tv_mode_from_name_test drm_get_tv_mode_from_name_valid_tests[] = { 554 TV_MODE_NAME("NTSC", DRM_MODE_TV_MODE_NTSC), 555 TV_MODE_NAME("NTSC-443", DRM_MODE_TV_MODE_NTSC_443), 556 TV_MODE_NAME("NTSC-J", DRM_MODE_TV_MODE_NTSC_J), 557 TV_MODE_NAME("PAL", DRM_MODE_TV_MODE_PAL), 558 TV_MODE_NAME("PAL-M", DRM_MODE_TV_MODE_PAL_M), 559 TV_MODE_NAME("PAL-N", DRM_MODE_TV_MODE_PAL_N), 560 TV_MODE_NAME("SECAM", DRM_MODE_TV_MODE_SECAM), 561 }; 562 563 static void 564 drm_get_tv_mode_from_name_valid_desc(const struct drm_get_tv_mode_from_name_test *t, 565 char *desc) 566 { 567 sprintf(desc, "%s", t->name); 568 } 569 570 KUNIT_ARRAY_PARAM(drm_get_tv_mode_from_name_valid, 571 drm_get_tv_mode_from_name_valid_tests, 572 drm_get_tv_mode_from_name_valid_desc); 573 574 static void drm_test_get_tv_mode_from_name_truncated(struct kunit *test) 575 { 576 const char *name = "NTS"; 577 int ret; 578 579 ret = drm_get_tv_mode_from_name(name, strlen(name)); 580 KUNIT_EXPECT_LT(test, ret, 0); 581 }; 582 583 static struct kunit_case drm_get_tv_mode_from_name_tests[] = { 584 KUNIT_CASE_PARAM(drm_test_get_tv_mode_from_name_valid, 585 drm_get_tv_mode_from_name_valid_gen_params), 586 KUNIT_CASE(drm_test_get_tv_mode_from_name_truncated), 587 { } 588 }; 589 590 static struct kunit_suite drm_get_tv_mode_from_name_test_suite = { 591 .name = "drm_get_tv_mode_from_name", 592 .test_cases = drm_get_tv_mode_from_name_tests, 593 }; 594 595 struct drm_hdmi_connector_get_broadcast_rgb_name_test { 596 unsigned int kind; 597 const char *expected_name; 598 }; 599 600 #define BROADCAST_RGB_TEST(_kind, _name) \ 601 { \ 602 .kind = _kind, \ 603 .expected_name = _name, \ 604 } 605 606 static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name(struct kunit *test) 607 { 608 const struct drm_hdmi_connector_get_broadcast_rgb_name_test *params = 609 test->param_value; 610 611 KUNIT_EXPECT_STREQ(test, 612 drm_hdmi_connector_get_broadcast_rgb_name(params->kind), 613 params->expected_name); 614 } 615 616 static const 617 struct drm_hdmi_connector_get_broadcast_rgb_name_test 618 drm_hdmi_connector_get_broadcast_rgb_name_valid_tests[] = { 619 BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic"), 620 BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_FULL, "Full"), 621 BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235"), 622 }; 623 624 static void 625 drm_hdmi_connector_get_broadcast_rgb_name_valid_desc(const struct drm_hdmi_connector_get_broadcast_rgb_name_test *t, 626 char *desc) 627 { 628 sprintf(desc, "%s", t->expected_name); 629 } 630 631 KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_broadcast_rgb_name_valid, 632 drm_hdmi_connector_get_broadcast_rgb_name_valid_tests, 633 drm_hdmi_connector_get_broadcast_rgb_name_valid_desc); 634 635 static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid(struct kunit *test) 636 { 637 KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_broadcast_rgb_name(3)); 638 }; 639 640 static struct kunit_case drm_hdmi_connector_get_broadcast_rgb_name_tests[] = { 641 KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_broadcast_rgb_name, 642 drm_hdmi_connector_get_broadcast_rgb_name_valid_gen_params), 643 KUNIT_CASE(drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid), 644 { } 645 }; 646 647 static struct kunit_suite drm_hdmi_connector_get_broadcast_rgb_name_test_suite = { 648 .name = "drm_hdmi_connector_get_broadcast_rgb_name", 649 .test_cases = drm_hdmi_connector_get_broadcast_rgb_name_tests, 650 }; 651 652 struct drm_hdmi_connector_get_output_format_name_test { 653 unsigned int kind; 654 const char *expected_name; 655 }; 656 657 #define OUTPUT_FORMAT_TEST(_kind, _name) \ 658 { \ 659 .kind = _kind, \ 660 .expected_name = _name, \ 661 } 662 663 static void drm_test_drm_hdmi_connector_get_output_format_name(struct kunit *test) 664 { 665 const struct drm_hdmi_connector_get_output_format_name_test *params = 666 test->param_value; 667 668 KUNIT_EXPECT_STREQ(test, 669 drm_hdmi_connector_get_output_format_name(params->kind), 670 params->expected_name); 671 } 672 673 static const 674 struct drm_hdmi_connector_get_output_format_name_test 675 drm_hdmi_connector_get_output_format_name_valid_tests[] = { 676 OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_RGB, "RGB"), 677 OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV420, "YUV 4:2:0"), 678 OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV422, "YUV 4:2:2"), 679 OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV444, "YUV 4:4:4"), 680 }; 681 682 static void 683 drm_hdmi_connector_get_output_format_name_valid_desc(const struct drm_hdmi_connector_get_output_format_name_test *t, 684 char *desc) 685 { 686 sprintf(desc, "%s", t->expected_name); 687 } 688 689 KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_output_format_name_valid, 690 drm_hdmi_connector_get_output_format_name_valid_tests, 691 drm_hdmi_connector_get_output_format_name_valid_desc); 692 693 static void drm_test_drm_hdmi_connector_get_output_format_name_invalid(struct kunit *test) 694 { 695 KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_output_format_name(4)); 696 }; 697 698 static struct kunit_case drm_hdmi_connector_get_output_format_name_tests[] = { 699 KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_output_format_name, 700 drm_hdmi_connector_get_output_format_name_valid_gen_params), 701 KUNIT_CASE(drm_test_drm_hdmi_connector_get_output_format_name_invalid), 702 { } 703 }; 704 705 static struct kunit_suite drm_hdmi_connector_get_output_format_name_test_suite = { 706 .name = "drm_hdmi_connector_get_output_format_name", 707 .test_cases = drm_hdmi_connector_get_output_format_name_tests, 708 }; 709 710 static void drm_test_drm_connector_attach_broadcast_rgb_property(struct kunit *test) 711 { 712 struct drm_connector_init_priv *priv = test->priv; 713 struct drm_connector *connector = &priv->connector; 714 struct drm_property *prop; 715 int ret; 716 717 ret = drmm_connector_init(&priv->drm, connector, 718 &dummy_funcs, 719 DRM_MODE_CONNECTOR_HDMIA, 720 &priv->ddc); 721 KUNIT_ASSERT_EQ(test, ret, 0); 722 723 ret = drm_connector_attach_broadcast_rgb_property(connector); 724 KUNIT_ASSERT_EQ(test, ret, 0); 725 726 prop = connector->broadcast_rgb_property; 727 KUNIT_ASSERT_NOT_NULL(test, prop); 728 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); 729 } 730 731 static void drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(struct kunit *test) 732 { 733 struct drm_connector_init_priv *priv = test->priv; 734 struct drm_connector *connector = &priv->connector; 735 struct drm_property *prop; 736 int ret; 737 738 ret = drmm_connector_hdmi_init(&priv->drm, connector, 739 "Vendor", "Product", 740 &dummy_funcs, 741 &dummy_hdmi_funcs, 742 DRM_MODE_CONNECTOR_HDMIA, 743 &priv->ddc, 744 BIT(HDMI_COLORSPACE_RGB), 745 8); 746 KUNIT_EXPECT_EQ(test, ret, 0); 747 748 ret = drm_connector_attach_broadcast_rgb_property(connector); 749 KUNIT_ASSERT_EQ(test, ret, 0); 750 751 prop = connector->broadcast_rgb_property; 752 KUNIT_ASSERT_NOT_NULL(test, prop); 753 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id)); 754 } 755 756 static struct kunit_case drm_connector_attach_broadcast_rgb_property_tests[] = { 757 KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property), 758 KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector), 759 { } 760 }; 761 762 static struct kunit_suite drm_connector_attach_broadcast_rgb_property_test_suite = { 763 .name = "drm_connector_attach_broadcast_rgb_property", 764 .init = drm_test_connector_init, 765 .test_cases = drm_connector_attach_broadcast_rgb_property_tests, 766 }; 767 768 /* 769 * Test that for a given mode, with 8bpc and an RGB output the TMDS 770 * character rate is equal to the mode pixel clock. 771 */ 772 static void drm_test_drm_hdmi_compute_mode_clock_rgb(struct kunit *test) 773 { 774 struct drm_connector_init_priv *priv = test->priv; 775 const struct drm_display_mode *mode; 776 unsigned long long rate; 777 struct drm_device *drm = &priv->drm; 778 779 mode = drm_display_mode_from_cea_vic(drm, 16); 780 KUNIT_ASSERT_NOT_NULL(test, mode); 781 782 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 783 784 rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB); 785 KUNIT_ASSERT_GT(test, rate, 0); 786 KUNIT_EXPECT_EQ(test, mode->clock * 1000ULL, rate); 787 } 788 789 /* 790 * Test that for a given mode, with 10bpc and an RGB output the TMDS 791 * character rate is equal to 1.25 times the mode pixel clock. 792 */ 793 static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc(struct kunit *test) 794 { 795 struct drm_connector_init_priv *priv = test->priv; 796 const struct drm_display_mode *mode; 797 unsigned long long rate; 798 struct drm_device *drm = &priv->drm; 799 800 mode = drm_display_mode_from_cea_vic(drm, 16); 801 KUNIT_ASSERT_NOT_NULL(test, mode); 802 803 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 804 805 rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB); 806 KUNIT_ASSERT_GT(test, rate, 0); 807 KUNIT_EXPECT_EQ(test, mode->clock * 1250, rate); 808 } 809 810 /* 811 * Test that for the VIC-1 mode, with 10bpc and an RGB output the TMDS 812 * character rate computation fails. 813 */ 814 static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1(struct kunit *test) 815 { 816 struct drm_connector_init_priv *priv = test->priv; 817 const struct drm_display_mode *mode; 818 unsigned long long rate; 819 struct drm_device *drm = &priv->drm; 820 821 mode = drm_display_mode_from_cea_vic(drm, 1); 822 KUNIT_ASSERT_NOT_NULL(test, mode); 823 824 rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB); 825 KUNIT_EXPECT_EQ(test, rate, 0); 826 } 827 828 /* 829 * Test that for a given mode, with 12bpc and an RGB output the TMDS 830 * character rate is equal to 1.5 times the mode pixel clock. 831 */ 832 static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc(struct kunit *test) 833 { 834 struct drm_connector_init_priv *priv = test->priv; 835 const struct drm_display_mode *mode; 836 unsigned long long rate; 837 struct drm_device *drm = &priv->drm; 838 839 mode = drm_display_mode_from_cea_vic(drm, 16); 840 KUNIT_ASSERT_NOT_NULL(test, mode); 841 842 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 843 844 rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB); 845 KUNIT_ASSERT_GT(test, rate, 0); 846 KUNIT_EXPECT_EQ(test, mode->clock * 1500, rate); 847 } 848 849 /* 850 * Test that for the VIC-1 mode, with 12bpc and an RGB output the TMDS 851 * character rate computation fails. 852 */ 853 static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1(struct kunit *test) 854 { 855 struct drm_connector_init_priv *priv = test->priv; 856 const struct drm_display_mode *mode; 857 unsigned long long rate; 858 struct drm_device *drm = &priv->drm; 859 860 mode = drm_display_mode_from_cea_vic(drm, 1); 861 KUNIT_ASSERT_NOT_NULL(test, mode); 862 863 rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB); 864 KUNIT_EXPECT_EQ(test, rate, 0); 865 } 866 867 /* 868 * Test that for a mode with the pixel repetition flag, the TMDS 869 * character rate is indeed double the mode pixel clock. 870 */ 871 static void drm_test_drm_hdmi_compute_mode_clock_rgb_double(struct kunit *test) 872 { 873 struct drm_connector_init_priv *priv = test->priv; 874 const struct drm_display_mode *mode; 875 unsigned long long rate; 876 struct drm_device *drm = &priv->drm; 877 878 mode = drm_display_mode_from_cea_vic(drm, 6); 879 KUNIT_ASSERT_NOT_NULL(test, mode); 880 881 KUNIT_ASSERT_TRUE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 882 883 rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB); 884 KUNIT_ASSERT_GT(test, rate, 0); 885 KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) * 2, rate); 886 } 887 888 /* 889 * Test that the TMDS character rate computation for the VIC modes 890 * explicitly listed in the spec as supporting YUV420 succeed and return 891 * half the mode pixel clock. 892 */ 893 static void drm_test_connector_hdmi_compute_mode_clock_yuv420_valid(struct kunit *test) 894 { 895 struct drm_connector_init_priv *priv = test->priv; 896 const struct drm_display_mode *mode; 897 struct drm_device *drm = &priv->drm; 898 unsigned long long rate; 899 unsigned int vic = *(unsigned int *)test->param_value; 900 901 mode = drm_display_mode_from_cea_vic(drm, vic); 902 KUNIT_ASSERT_NOT_NULL(test, mode); 903 904 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 905 906 rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV420); 907 KUNIT_ASSERT_GT(test, rate, 0); 908 KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) / 2, rate); 909 } 910 911 static const unsigned int drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[] = { 912 96, 97, 101, 102, 106, 107, 913 }; 914 915 static void drm_hdmi_compute_mode_clock_yuv420_vic_desc(const unsigned int *vic, char *desc) 916 { 917 sprintf(desc, "VIC %u", *vic); 918 } 919 920 KUNIT_ARRAY_PARAM(drm_hdmi_compute_mode_clock_yuv420_valid, 921 drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests, 922 drm_hdmi_compute_mode_clock_yuv420_vic_desc); 923 924 /* 925 * Test that for a given mode listed supporting it and an YUV420 output 926 * with 10bpc, the TMDS character rate is equal to 0.625 times the mode 927 * pixel clock. 928 */ 929 static void drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc(struct kunit *test) 930 { 931 struct drm_connector_init_priv *priv = test->priv; 932 const struct drm_display_mode *mode; 933 struct drm_device *drm = &priv->drm; 934 unsigned int vic = 935 drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0]; 936 unsigned long long rate; 937 938 mode = drm_display_mode_from_cea_vic(drm, vic); 939 KUNIT_ASSERT_NOT_NULL(test, mode); 940 941 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 942 943 rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV420); 944 KUNIT_ASSERT_GT(test, rate, 0); 945 946 KUNIT_EXPECT_EQ(test, mode->clock * 625, rate); 947 } 948 949 /* 950 * Test that for a given mode listed supporting it and an YUV420 output 951 * with 12bpc, the TMDS character rate is equal to 0.75 times the mode 952 * pixel clock. 953 */ 954 static void drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc(struct kunit *test) 955 { 956 struct drm_connector_init_priv *priv = test->priv; 957 const struct drm_display_mode *mode; 958 struct drm_device *drm = &priv->drm; 959 unsigned int vic = 960 drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0]; 961 unsigned long long rate; 962 963 mode = drm_display_mode_from_cea_vic(drm, vic); 964 KUNIT_ASSERT_NOT_NULL(test, mode); 965 966 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 967 968 rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV420); 969 KUNIT_ASSERT_GT(test, rate, 0); 970 971 KUNIT_EXPECT_EQ(test, mode->clock * 750, rate); 972 } 973 974 /* 975 * Test that for a given mode, the computation of the TMDS character 976 * rate with 8bpc and a YUV422 output succeeds and returns a rate equal 977 * to the mode pixel clock. 978 */ 979 static void drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc(struct kunit *test) 980 { 981 struct drm_connector_init_priv *priv = test->priv; 982 const struct drm_display_mode *mode; 983 struct drm_device *drm = &priv->drm; 984 unsigned long long rate; 985 986 mode = drm_display_mode_from_cea_vic(drm, 16); 987 KUNIT_ASSERT_NOT_NULL(test, mode); 988 989 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 990 991 rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV422); 992 KUNIT_ASSERT_GT(test, rate, 0); 993 KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate); 994 } 995 996 /* 997 * Test that for a given mode, the computation of the TMDS character 998 * rate with 10bpc and a YUV422 output succeeds and returns a rate equal 999 * to the mode pixel clock. 1000 */ 1001 static void drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc(struct kunit *test) 1002 { 1003 struct drm_connector_init_priv *priv = test->priv; 1004 const struct drm_display_mode *mode; 1005 struct drm_device *drm = &priv->drm; 1006 unsigned long long rate; 1007 1008 mode = drm_display_mode_from_cea_vic(drm, 16); 1009 KUNIT_ASSERT_NOT_NULL(test, mode); 1010 1011 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 1012 1013 rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV422); 1014 KUNIT_ASSERT_GT(test, rate, 0); 1015 KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate); 1016 } 1017 1018 /* 1019 * Test that for a given mode, the computation of the TMDS character 1020 * rate with 12bpc and a YUV422 output succeeds and returns a rate equal 1021 * to the mode pixel clock. 1022 */ 1023 static void drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc(struct kunit *test) 1024 { 1025 struct drm_connector_init_priv *priv = test->priv; 1026 const struct drm_display_mode *mode; 1027 struct drm_device *drm = &priv->drm; 1028 unsigned long long rate; 1029 1030 mode = drm_display_mode_from_cea_vic(drm, 16); 1031 KUNIT_ASSERT_NOT_NULL(test, mode); 1032 1033 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK); 1034 1035 rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV422); 1036 KUNIT_ASSERT_GT(test, rate, 0); 1037 KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate); 1038 } 1039 1040 static struct kunit_case drm_hdmi_compute_mode_clock_tests[] = { 1041 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb), 1042 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc), 1043 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1), 1044 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc), 1045 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1), 1046 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_double), 1047 KUNIT_CASE_PARAM(drm_test_connector_hdmi_compute_mode_clock_yuv420_valid, 1048 drm_hdmi_compute_mode_clock_yuv420_valid_gen_params), 1049 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc), 1050 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc), 1051 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc), 1052 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc), 1053 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc), 1054 { } 1055 }; 1056 1057 static struct kunit_suite drm_hdmi_compute_mode_clock_test_suite = { 1058 .name = "drm_test_connector_hdmi_compute_mode_clock", 1059 .init = drm_test_connector_init, 1060 .test_cases = drm_hdmi_compute_mode_clock_tests, 1061 }; 1062 1063 kunit_test_suites( 1064 &drmm_connector_hdmi_init_test_suite, 1065 &drmm_connector_init_test_suite, 1066 &drm_connector_attach_broadcast_rgb_property_test_suite, 1067 &drm_get_tv_mode_from_name_test_suite, 1068 &drm_hdmi_compute_mode_clock_test_suite, 1069 &drm_hdmi_connector_get_broadcast_rgb_name_test_suite, 1070 &drm_hdmi_connector_get_output_format_name_test_suite 1071 ); 1072 1073 MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>"); 1074 MODULE_LICENSE("GPL"); 1075