1 // SPDX-License-Identifier: GPL-2.0 2 3 /* 4 * Kunit test for drm_hdmi_state_helper functions 5 */ 6 7 #include <drm/drm_atomic.h> 8 #include <drm/drm_atomic_state_helper.h> 9 #include <drm/drm_atomic_uapi.h> 10 #include <drm/drm_drv.h> 11 #include <drm/drm_edid.h> 12 #include <drm/drm_connector.h> 13 #include <drm/drm_fourcc.h> 14 #include <drm/drm_kunit_helpers.h> 15 #include <drm/drm_managed.h> 16 #include <drm/drm_modeset_helper_vtables.h> 17 #include <drm/drm_print.h> 18 #include <drm/drm_probe_helper.h> 19 20 #include <drm/display/drm_hdmi_helper.h> 21 #include <drm/display/drm_hdmi_state_helper.h> 22 23 #include "../drm_crtc_internal.h" 24 25 #include <kunit/test.h> 26 27 #include "drm_kunit_edid.h" 28 29 struct drm_atomic_helper_connector_hdmi_priv { 30 struct drm_device drm; 31 struct drm_plane *plane; 32 struct drm_crtc *crtc; 33 struct drm_encoder encoder; 34 struct drm_connector connector; 35 36 const void *current_edid; 37 size_t current_edid_len; 38 }; 39 40 #define connector_to_priv(c) \ 41 container_of_const(c, struct drm_atomic_helper_connector_hdmi_priv, connector) 42 43 static struct drm_display_mode *find_preferred_mode(struct drm_connector *connector) 44 { 45 struct drm_device *drm = connector->dev; 46 struct drm_display_mode *mode, *preferred; 47 48 mutex_lock(&drm->mode_config.mutex); 49 preferred = list_first_entry_or_null(&connector->modes, struct drm_display_mode, head); 50 list_for_each_entry(mode, &connector->modes, head) 51 if (mode->type & DRM_MODE_TYPE_PREFERRED) 52 preferred = mode; 53 mutex_unlock(&drm->mode_config.mutex); 54 55 return preferred; 56 } 57 58 static int set_connector_edid(struct kunit *test, struct drm_connector *connector, 59 const void *edid, size_t edid_len) 60 { 61 struct drm_atomic_helper_connector_hdmi_priv *priv = 62 connector_to_priv(connector); 63 struct drm_device *drm = connector->dev; 64 int ret; 65 66 priv->current_edid = edid; 67 priv->current_edid_len = edid_len; 68 69 mutex_lock(&drm->mode_config.mutex); 70 ret = connector->funcs->fill_modes(connector, 4096, 4096); 71 mutex_unlock(&drm->mode_config.mutex); 72 73 return ret; 74 } 75 76 static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_funcs = { 77 }; 78 79 static enum drm_mode_status 80 reject_connector_tmds_char_rate_valid(const struct drm_connector *connector, 81 const struct drm_display_mode *mode, 82 unsigned long long tmds_rate) 83 { 84 return MODE_BAD; 85 } 86 87 static const struct drm_connector_hdmi_funcs reject_connector_hdmi_funcs = { 88 .tmds_char_rate_valid = reject_connector_tmds_char_rate_valid, 89 }; 90 91 static enum drm_mode_status 92 reject_100mhz_connector_tmds_char_rate_valid(const struct drm_connector *connector, 93 const struct drm_display_mode *mode, 94 unsigned long long tmds_rate) 95 { 96 return (tmds_rate > 100ULL * 1000 * 1000) ? MODE_BAD : MODE_OK; 97 } 98 99 static const struct drm_connector_hdmi_funcs reject_100mhz_connector_hdmi_funcs = { 100 .tmds_char_rate_valid = reject_100mhz_connector_tmds_char_rate_valid, 101 }; 102 103 static int dummy_connector_get_modes(struct drm_connector *connector) 104 { 105 struct drm_atomic_helper_connector_hdmi_priv *priv = 106 connector_to_priv(connector); 107 const struct drm_edid *edid; 108 unsigned int num_modes; 109 110 edid = drm_edid_alloc(priv->current_edid, priv->current_edid_len); 111 if (!edid) 112 return -EINVAL; 113 114 drm_edid_connector_update(connector, edid); 115 num_modes = drm_edid_connector_add_modes(connector); 116 117 drm_edid_free(edid); 118 119 return num_modes; 120 } 121 122 static const struct drm_connector_helper_funcs dummy_connector_helper_funcs = { 123 .atomic_check = drm_atomic_helper_connector_hdmi_check, 124 .get_modes = dummy_connector_get_modes, 125 .mode_valid = drm_hdmi_connector_mode_valid, 126 }; 127 128 static void dummy_hdmi_connector_reset(struct drm_connector *connector) 129 { 130 drm_atomic_helper_connector_reset(connector); 131 __drm_atomic_helper_connector_hdmi_reset(connector, connector->state); 132 } 133 134 static const struct drm_connector_funcs dummy_connector_funcs = { 135 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 136 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 137 .fill_modes = drm_helper_probe_single_connector_modes, 138 .reset = dummy_hdmi_connector_reset, 139 }; 140 141 static 142 struct drm_atomic_helper_connector_hdmi_priv * 143 __connector_hdmi_init(struct kunit *test, 144 unsigned int formats, 145 unsigned int max_bpc, 146 const struct drm_connector_hdmi_funcs *hdmi_funcs, 147 const void *edid_data, size_t edid_len) 148 { 149 struct drm_atomic_helper_connector_hdmi_priv *priv; 150 struct drm_connector *conn; 151 struct drm_encoder *enc; 152 struct drm_device *drm; 153 struct device *dev; 154 int ret; 155 156 dev = drm_kunit_helper_alloc_device(test); 157 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); 158 159 priv = drm_kunit_helper_alloc_drm_device(test, dev, 160 struct drm_atomic_helper_connector_hdmi_priv, drm, 161 DRIVER_MODESET | DRIVER_ATOMIC); 162 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 163 test->priv = priv; 164 165 drm = &priv->drm; 166 priv->plane = drm_kunit_helper_create_primary_plane(test, drm, 167 NULL, 168 NULL, 169 NULL, 0, 170 NULL); 171 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->plane); 172 173 priv->crtc = drm_kunit_helper_create_crtc(test, drm, 174 priv->plane, NULL, 175 NULL, 176 NULL); 177 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->crtc); 178 179 enc = &priv->encoder; 180 ret = drmm_encoder_init(drm, enc, NULL, DRM_MODE_ENCODER_TMDS, NULL); 181 KUNIT_ASSERT_EQ(test, ret, 0); 182 183 enc->possible_crtcs = drm_crtc_mask(priv->crtc); 184 185 conn = &priv->connector; 186 conn->ycbcr_420_allowed = !!(formats & BIT(HDMI_COLORSPACE_YUV420)); 187 188 ret = drmm_connector_hdmi_init(drm, conn, 189 "Vendor", "Product", 190 &dummy_connector_funcs, 191 hdmi_funcs, 192 DRM_MODE_CONNECTOR_HDMIA, 193 NULL, 194 formats, 195 max_bpc); 196 KUNIT_ASSERT_EQ(test, ret, 0); 197 198 drm_connector_helper_add(conn, &dummy_connector_helper_funcs); 199 drm_connector_attach_encoder(conn, enc); 200 201 drm_mode_config_reset(drm); 202 203 if (edid_data && edid_len) { 204 ret = set_connector_edid(test, &priv->connector, edid_data, edid_len); 205 KUNIT_ASSERT_GT(test, ret, 0); 206 } 207 208 return priv; 209 } 210 211 #define drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, formats, max_bpc, funcs, edid) \ 212 __connector_hdmi_init(test, formats, max_bpc, funcs, edid, ARRAY_SIZE(edid)) 213 214 static 215 struct drm_atomic_helper_connector_hdmi_priv * 216 drm_kunit_helper_connector_hdmi_init(struct kunit *test, 217 unsigned int formats, 218 unsigned int max_bpc) 219 { 220 return drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 221 formats, 222 max_bpc, 223 &dummy_connector_hdmi_funcs, 224 test_edid_hdmi_1080p_rgb_max_200mhz); 225 } 226 227 /* 228 * Test that if we change the RGB quantization property to a different 229 * value, we trigger a mode change on the connector's CRTC, which will 230 * in turn disable/enable the connector. 231 */ 232 static void drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit *test) 233 { 234 struct drm_atomic_helper_connector_hdmi_priv *priv; 235 struct drm_modeset_acquire_ctx ctx; 236 struct drm_connector_state *old_conn_state; 237 struct drm_connector_state *new_conn_state; 238 struct drm_crtc_state *crtc_state; 239 struct drm_atomic_state *state; 240 struct drm_display_mode *preferred; 241 struct drm_connector *conn; 242 struct drm_device *drm; 243 struct drm_crtc *crtc; 244 int ret; 245 246 priv = drm_kunit_helper_connector_hdmi_init(test, 247 BIT(HDMI_COLORSPACE_RGB), 248 8); 249 KUNIT_ASSERT_NOT_NULL(test, priv); 250 251 drm = &priv->drm; 252 crtc = priv->crtc; 253 conn = &priv->connector; 254 255 preferred = find_preferred_mode(conn); 256 KUNIT_ASSERT_NOT_NULL(test, preferred); 257 258 drm_modeset_acquire_init(&ctx, 0); 259 260 retry_conn_enable: 261 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 262 crtc, conn, 263 preferred, 264 &ctx); 265 if (ret == -EDEADLK) { 266 ret = drm_modeset_backoff(&ctx); 267 if (!ret) 268 goto retry_conn_enable; 269 } 270 KUNIT_ASSERT_EQ(test, ret, 0); 271 272 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 273 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 274 275 new_conn_state = drm_atomic_get_connector_state(state, conn); 276 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 277 278 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 279 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 280 281 new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL; 282 283 KUNIT_ASSERT_NE(test, 284 old_conn_state->hdmi.broadcast_rgb, 285 new_conn_state->hdmi.broadcast_rgb); 286 287 ret = drm_atomic_check_only(state); 288 KUNIT_ASSERT_EQ(test, ret, 0); 289 290 new_conn_state = drm_atomic_get_new_connector_state(state, conn); 291 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 292 KUNIT_EXPECT_EQ(test, new_conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_FULL); 293 294 crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 295 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 296 KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed); 297 298 drm_modeset_drop_locks(&ctx); 299 drm_modeset_acquire_fini(&ctx); 300 } 301 302 /* 303 * Test that if we set the RGB quantization property to the same value, 304 * we don't trigger a mode change on the connector's CRTC and leave the 305 * connector unaffected. 306 */ 307 static void drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *test) 308 { 309 struct drm_atomic_helper_connector_hdmi_priv *priv; 310 struct drm_modeset_acquire_ctx ctx; 311 struct drm_connector_state *old_conn_state; 312 struct drm_connector_state *new_conn_state; 313 struct drm_crtc_state *crtc_state; 314 struct drm_atomic_state *state; 315 struct drm_display_mode *preferred; 316 struct drm_connector *conn; 317 struct drm_device *drm; 318 struct drm_crtc *crtc; 319 int ret; 320 321 priv = drm_kunit_helper_connector_hdmi_init(test, 322 BIT(HDMI_COLORSPACE_RGB), 323 8); 324 KUNIT_ASSERT_NOT_NULL(test, priv); 325 326 drm = &priv->drm; 327 crtc = priv->crtc; 328 conn = &priv->connector; 329 330 preferred = find_preferred_mode(conn); 331 KUNIT_ASSERT_NOT_NULL(test, preferred); 332 333 drm_modeset_acquire_init(&ctx, 0); 334 335 retry_conn_enable: 336 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 337 crtc, conn, 338 preferred, 339 &ctx); 340 if (ret == -EDEADLK) { 341 ret = drm_modeset_backoff(&ctx); 342 if (!ret) 343 goto retry_conn_enable; 344 } 345 KUNIT_ASSERT_EQ(test, ret, 0); 346 347 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 348 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 349 350 new_conn_state = drm_atomic_get_connector_state(state, conn); 351 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 352 353 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 354 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 355 356 new_conn_state->hdmi.broadcast_rgb = old_conn_state->hdmi.broadcast_rgb; 357 358 ret = drm_atomic_check_only(state); 359 KUNIT_ASSERT_EQ(test, ret, 0); 360 361 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 362 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 363 364 new_conn_state = drm_atomic_get_new_connector_state(state, conn); 365 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 366 367 KUNIT_EXPECT_EQ(test, 368 old_conn_state->hdmi.broadcast_rgb, 369 new_conn_state->hdmi.broadcast_rgb); 370 371 crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 372 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 373 KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed); 374 375 drm_modeset_drop_locks(&ctx); 376 drm_modeset_acquire_fini(&ctx); 377 } 378 379 /* 380 * Test that for an HDMI connector, with an HDMI monitor, if the 381 * Broadcast RGB property is set to auto with a mode that isn't the 382 * VIC-1 mode, we will get a limited RGB Quantization Range. 383 */ 384 static void drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit *test) 385 { 386 struct drm_atomic_helper_connector_hdmi_priv *priv; 387 struct drm_modeset_acquire_ctx ctx; 388 struct drm_connector_state *conn_state; 389 struct drm_atomic_state *state; 390 struct drm_display_mode *preferred; 391 struct drm_connector *conn; 392 struct drm_device *drm; 393 struct drm_crtc *crtc; 394 int ret; 395 396 priv = drm_kunit_helper_connector_hdmi_init(test, 397 BIT(HDMI_COLORSPACE_RGB), 398 8); 399 KUNIT_ASSERT_NOT_NULL(test, priv); 400 401 drm = &priv->drm; 402 crtc = priv->crtc; 403 conn = &priv->connector; 404 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 405 406 preferred = find_preferred_mode(conn); 407 KUNIT_ASSERT_NOT_NULL(test, preferred); 408 KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); 409 410 drm_modeset_acquire_init(&ctx, 0); 411 412 retry_conn_enable: 413 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 414 crtc, conn, 415 preferred, 416 &ctx); 417 if (ret == -EDEADLK) { 418 ret = drm_modeset_backoff(&ctx); 419 if (!ret) 420 goto retry_conn_enable; 421 } 422 KUNIT_ASSERT_EQ(test, ret, 0); 423 424 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 425 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 426 427 conn_state = drm_atomic_get_connector_state(state, conn); 428 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 429 430 KUNIT_ASSERT_EQ(test, 431 conn_state->hdmi.broadcast_rgb, 432 DRM_HDMI_BROADCAST_RGB_AUTO); 433 434 ret = drm_atomic_check_only(state); 435 KUNIT_ASSERT_EQ(test, ret, 0); 436 437 conn_state = drm_atomic_get_new_connector_state(state, conn); 438 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 439 440 KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); 441 442 drm_modeset_drop_locks(&ctx); 443 drm_modeset_acquire_fini(&ctx); 444 } 445 446 /* 447 * Test that for an HDMI connector, with an HDMI monitor, if the 448 * Broadcast RGB property is set to auto with a VIC-1 mode, we will get 449 * a full RGB Quantization Range. 450 */ 451 static void drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit *test) 452 { 453 struct drm_atomic_helper_connector_hdmi_priv *priv; 454 struct drm_modeset_acquire_ctx ctx; 455 struct drm_connector_state *conn_state; 456 struct drm_atomic_state *state; 457 struct drm_display_mode *mode; 458 struct drm_connector *conn; 459 struct drm_device *drm; 460 struct drm_crtc *crtc; 461 int ret; 462 463 priv = drm_kunit_helper_connector_hdmi_init(test, 464 BIT(HDMI_COLORSPACE_RGB), 465 8); 466 KUNIT_ASSERT_NOT_NULL(test, priv); 467 468 drm = &priv->drm; 469 conn = &priv->connector; 470 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 471 472 drm_modeset_acquire_init(&ctx, 0); 473 474 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); 475 KUNIT_ASSERT_NOT_NULL(test, mode); 476 477 crtc = priv->crtc; 478 479 retry_conn_enable: 480 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 481 crtc, conn, 482 mode, 483 &ctx); 484 if (ret == -EDEADLK) { 485 ret = drm_modeset_backoff(&ctx); 486 if (!ret) 487 goto retry_conn_enable; 488 } 489 KUNIT_ASSERT_EQ(test, ret, 0); 490 491 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 492 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 493 494 conn_state = drm_atomic_get_connector_state(state, conn); 495 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 496 497 KUNIT_ASSERT_EQ(test, 498 conn_state->hdmi.broadcast_rgb, 499 DRM_HDMI_BROADCAST_RGB_AUTO); 500 501 ret = drm_atomic_check_only(state); 502 KUNIT_ASSERT_EQ(test, ret, 0); 503 504 conn_state = drm_atomic_get_new_connector_state(state, conn); 505 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 506 507 KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range); 508 509 drm_modeset_drop_locks(&ctx); 510 drm_modeset_acquire_fini(&ctx); 511 } 512 513 /* 514 * Test that for an HDMI connector, with an HDMI monitor, if the 515 * Broadcast RGB property is set to full with a mode that isn't the 516 * VIC-1 mode, we will get a full RGB Quantization Range. 517 */ 518 static void drm_test_check_broadcast_rgb_full_cea_mode(struct kunit *test) 519 { 520 struct drm_atomic_helper_connector_hdmi_priv *priv; 521 struct drm_modeset_acquire_ctx ctx; 522 struct drm_connector_state *conn_state; 523 struct drm_atomic_state *state; 524 struct drm_display_mode *preferred; 525 struct drm_connector *conn; 526 struct drm_device *drm; 527 struct drm_crtc *crtc; 528 int ret; 529 530 priv = drm_kunit_helper_connector_hdmi_init(test, 531 BIT(HDMI_COLORSPACE_RGB), 532 8); 533 KUNIT_ASSERT_NOT_NULL(test, priv); 534 535 drm = &priv->drm; 536 crtc = priv->crtc; 537 conn = &priv->connector; 538 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 539 540 preferred = find_preferred_mode(conn); 541 KUNIT_ASSERT_NOT_NULL(test, preferred); 542 KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); 543 544 drm_modeset_acquire_init(&ctx, 0); 545 546 retry_conn_enable: 547 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 548 crtc, conn, 549 preferred, 550 &ctx); 551 if (ret == -EDEADLK) { 552 ret = drm_modeset_backoff(&ctx); 553 if (!ret) 554 goto retry_conn_enable; 555 } 556 KUNIT_ASSERT_EQ(test, ret, 0); 557 558 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 559 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 560 561 conn_state = drm_atomic_get_connector_state(state, conn); 562 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 563 564 conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL; 565 566 ret = drm_atomic_check_only(state); 567 KUNIT_ASSERT_EQ(test, ret, 0); 568 569 conn_state = drm_atomic_get_new_connector_state(state, conn); 570 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 571 572 KUNIT_ASSERT_EQ(test, 573 conn_state->hdmi.broadcast_rgb, 574 DRM_HDMI_BROADCAST_RGB_FULL); 575 576 KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range); 577 578 drm_modeset_drop_locks(&ctx); 579 drm_modeset_acquire_fini(&ctx); 580 } 581 582 /* 583 * Test that for an HDMI connector, with an HDMI monitor, if the 584 * Broadcast RGB property is set to full with a VIC-1 mode, we will get 585 * a full RGB Quantization Range. 586 */ 587 static void drm_test_check_broadcast_rgb_full_cea_mode_vic_1(struct kunit *test) 588 { 589 struct drm_atomic_helper_connector_hdmi_priv *priv; 590 struct drm_modeset_acquire_ctx ctx; 591 struct drm_connector_state *conn_state; 592 struct drm_atomic_state *state; 593 struct drm_display_mode *mode; 594 struct drm_connector *conn; 595 struct drm_device *drm; 596 struct drm_crtc *crtc; 597 int ret; 598 599 priv = drm_kunit_helper_connector_hdmi_init(test, 600 BIT(HDMI_COLORSPACE_RGB), 601 8); 602 KUNIT_ASSERT_NOT_NULL(test, priv); 603 604 drm = &priv->drm; 605 conn = &priv->connector; 606 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 607 608 drm_modeset_acquire_init(&ctx, 0); 609 610 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); 611 KUNIT_ASSERT_NOT_NULL(test, mode); 612 613 crtc = priv->crtc; 614 615 retry_conn_enable: 616 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 617 crtc, conn, 618 mode, 619 &ctx); 620 if (ret == -EDEADLK) { 621 ret = drm_modeset_backoff(&ctx); 622 if (!ret) 623 goto retry_conn_enable; 624 } 625 KUNIT_ASSERT_EQ(test, ret, 0); 626 627 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 628 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 629 630 conn_state = drm_atomic_get_connector_state(state, conn); 631 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 632 633 conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL; 634 635 ret = drm_atomic_check_only(state); 636 KUNIT_ASSERT_EQ(test, ret, 0); 637 638 conn_state = drm_atomic_get_new_connector_state(state, conn); 639 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 640 641 KUNIT_ASSERT_EQ(test, 642 conn_state->hdmi.broadcast_rgb, 643 DRM_HDMI_BROADCAST_RGB_FULL); 644 645 KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range); 646 647 drm_modeset_drop_locks(&ctx); 648 drm_modeset_acquire_fini(&ctx); 649 } 650 651 /* 652 * Test that for an HDMI connector, with an HDMI monitor, if the 653 * Broadcast RGB property is set to limited with a mode that isn't the 654 * VIC-1 mode, we will get a limited RGB Quantization Range. 655 */ 656 static void drm_test_check_broadcast_rgb_limited_cea_mode(struct kunit *test) 657 { 658 struct drm_atomic_helper_connector_hdmi_priv *priv; 659 struct drm_modeset_acquire_ctx ctx; 660 struct drm_connector_state *conn_state; 661 struct drm_atomic_state *state; 662 struct drm_display_mode *preferred; 663 struct drm_connector *conn; 664 struct drm_device *drm; 665 struct drm_crtc *crtc; 666 int ret; 667 668 priv = drm_kunit_helper_connector_hdmi_init(test, 669 BIT(HDMI_COLORSPACE_RGB), 670 8); 671 KUNIT_ASSERT_NOT_NULL(test, priv); 672 673 drm = &priv->drm; 674 crtc = priv->crtc; 675 conn = &priv->connector; 676 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 677 678 preferred = find_preferred_mode(conn); 679 KUNIT_ASSERT_NOT_NULL(test, preferred); 680 KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); 681 682 drm_modeset_acquire_init(&ctx, 0); 683 684 retry_conn_enable: 685 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 686 crtc, conn, 687 preferred, 688 &ctx); 689 if (ret == -EDEADLK) { 690 ret = drm_modeset_backoff(&ctx); 691 if (!ret) 692 goto retry_conn_enable; 693 } 694 KUNIT_ASSERT_EQ(test, ret, 0); 695 696 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 697 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 698 699 conn_state = drm_atomic_get_connector_state(state, conn); 700 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 701 702 conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED; 703 704 ret = drm_atomic_check_only(state); 705 KUNIT_ASSERT_EQ(test, ret, 0); 706 707 conn_state = drm_atomic_get_new_connector_state(state, conn); 708 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 709 710 KUNIT_ASSERT_EQ(test, 711 conn_state->hdmi.broadcast_rgb, 712 DRM_HDMI_BROADCAST_RGB_LIMITED); 713 714 KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); 715 716 drm_modeset_drop_locks(&ctx); 717 drm_modeset_acquire_fini(&ctx); 718 } 719 720 /* 721 * Test that for an HDMI connector, with an HDMI monitor, if the 722 * Broadcast RGB property is set to limited with a VIC-1 mode, we will 723 * get a limited RGB Quantization Range. 724 */ 725 static void drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit *test) 726 { 727 struct drm_atomic_helper_connector_hdmi_priv *priv; 728 struct drm_modeset_acquire_ctx ctx; 729 struct drm_connector_state *conn_state; 730 struct drm_atomic_state *state; 731 struct drm_display_mode *mode; 732 struct drm_connector *conn; 733 struct drm_device *drm; 734 struct drm_crtc *crtc; 735 int ret; 736 737 priv = drm_kunit_helper_connector_hdmi_init(test, 738 BIT(HDMI_COLORSPACE_RGB), 739 8); 740 KUNIT_ASSERT_NOT_NULL(test, priv); 741 742 drm = &priv->drm; 743 conn = &priv->connector; 744 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 745 746 drm_modeset_acquire_init(&ctx, 0); 747 748 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); 749 KUNIT_ASSERT_NOT_NULL(test, mode); 750 751 crtc = priv->crtc; 752 753 retry_conn_enable: 754 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 755 crtc, conn, 756 mode, 757 &ctx); 758 if (ret == -EDEADLK) { 759 ret = drm_modeset_backoff(&ctx); 760 if (!ret) 761 goto retry_conn_enable; 762 } 763 KUNIT_ASSERT_EQ(test, ret, 0); 764 765 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 766 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 767 768 conn_state = drm_atomic_get_connector_state(state, conn); 769 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 770 771 conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED; 772 773 ret = drm_atomic_check_only(state); 774 KUNIT_ASSERT_EQ(test, ret, 0); 775 776 conn_state = drm_atomic_get_new_connector_state(state, conn); 777 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 778 779 KUNIT_ASSERT_EQ(test, 780 conn_state->hdmi.broadcast_rgb, 781 DRM_HDMI_BROADCAST_RGB_LIMITED); 782 783 KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); 784 785 drm_modeset_drop_locks(&ctx); 786 drm_modeset_acquire_fini(&ctx); 787 } 788 789 /* 790 * Test that for an HDMI connector, with an HDMI monitor, we will 791 * get a limited RGB Quantization Range with a YUV420 mode, no 792 * matter what the value of the Broadcast RGB property is set to. 793 */ 794 static void drm_test_check_broadcast_rgb_cea_mode_yuv420(struct kunit *test) 795 { 796 struct drm_atomic_helper_connector_hdmi_priv *priv; 797 enum drm_hdmi_broadcast_rgb broadcast_rgb; 798 struct drm_modeset_acquire_ctx ctx; 799 struct drm_connector_state *conn_state; 800 struct drm_atomic_state *state; 801 struct drm_display_mode *mode; 802 struct drm_connector *conn; 803 struct drm_device *drm; 804 struct drm_crtc *crtc; 805 int ret; 806 807 broadcast_rgb = *(enum drm_hdmi_broadcast_rgb *)test->param_value; 808 809 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 810 BIT(HDMI_COLORSPACE_RGB) | 811 BIT(HDMI_COLORSPACE_YUV420), 812 8, 813 &dummy_connector_hdmi_funcs, 814 test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); 815 KUNIT_ASSERT_NOT_NULL(test, priv); 816 817 drm = &priv->drm; 818 crtc = priv->crtc; 819 conn = &priv->connector; 820 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 821 822 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95); 823 KUNIT_ASSERT_NOT_NULL(test, mode); 824 825 drm_modeset_acquire_init(&ctx, 0); 826 827 retry_conn_enable: 828 ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, 829 mode, &ctx); 830 if (ret == -EDEADLK) { 831 ret = drm_modeset_backoff(&ctx); 832 if (!ret) 833 goto retry_conn_enable; 834 } 835 KUNIT_ASSERT_EQ(test, ret, 0); 836 837 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 838 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 839 840 retry_conn_state: 841 conn_state = drm_atomic_get_connector_state(state, conn); 842 if (PTR_ERR(conn_state) == -EDEADLK) { 843 drm_atomic_state_clear(state); 844 ret = drm_modeset_backoff(&ctx); 845 if (!ret) 846 goto retry_conn_state; 847 } 848 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 849 850 conn_state->hdmi.broadcast_rgb = broadcast_rgb; 851 852 ret = drm_atomic_check_only(state); 853 if (ret == -EDEADLK) { 854 drm_atomic_state_clear(state); 855 ret = drm_modeset_backoff(&ctx); 856 if (!ret) 857 goto retry_conn_state; 858 } 859 KUNIT_ASSERT_EQ(test, ret, 0); 860 861 conn_state = drm_atomic_get_new_connector_state(state, conn); 862 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 863 864 KUNIT_ASSERT_EQ(test, conn_state->hdmi.broadcast_rgb, broadcast_rgb); 865 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420); 866 867 KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); 868 869 drm_modeset_drop_locks(&ctx); 870 drm_modeset_acquire_fini(&ctx); 871 } 872 873 static const enum drm_hdmi_broadcast_rgb check_broadcast_rgb_cea_mode_yuv420_tests[] = { 874 DRM_HDMI_BROADCAST_RGB_AUTO, 875 DRM_HDMI_BROADCAST_RGB_FULL, 876 DRM_HDMI_BROADCAST_RGB_LIMITED, 877 }; 878 879 static void 880 check_broadcast_rgb_cea_mode_yuv420_desc(const enum drm_hdmi_broadcast_rgb *broadcast_rgb, 881 char *desc) 882 { 883 sprintf(desc, "%s", drm_hdmi_connector_get_broadcast_rgb_name(*broadcast_rgb)); 884 } 885 886 KUNIT_ARRAY_PARAM(check_broadcast_rgb_cea_mode_yuv420, 887 check_broadcast_rgb_cea_mode_yuv420_tests, 888 check_broadcast_rgb_cea_mode_yuv420_desc); 889 890 /* 891 * Test that if we change the maximum bpc property to a different value, 892 * we trigger a mode change on the connector's CRTC, which will in turn 893 * disable/enable the connector. 894 */ 895 static void drm_test_check_output_bpc_crtc_mode_changed(struct kunit *test) 896 { 897 struct drm_atomic_helper_connector_hdmi_priv *priv; 898 struct drm_modeset_acquire_ctx ctx; 899 struct drm_connector_state *old_conn_state; 900 struct drm_connector_state *new_conn_state; 901 struct drm_crtc_state *crtc_state; 902 struct drm_atomic_state *state; 903 struct drm_display_mode *preferred; 904 struct drm_connector *conn; 905 struct drm_device *drm; 906 struct drm_crtc *crtc; 907 int ret; 908 909 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 910 BIT(HDMI_COLORSPACE_RGB), 911 10, 912 &dummy_connector_hdmi_funcs, 913 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); 914 KUNIT_ASSERT_NOT_NULL(test, priv); 915 916 drm = &priv->drm; 917 crtc = priv->crtc; 918 conn = &priv->connector; 919 preferred = find_preferred_mode(conn); 920 KUNIT_ASSERT_NOT_NULL(test, preferred); 921 922 drm_modeset_acquire_init(&ctx, 0); 923 924 retry_conn_enable: 925 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 926 crtc, conn, 927 preferred, 928 &ctx); 929 if (ret == -EDEADLK) { 930 ret = drm_modeset_backoff(&ctx); 931 if (!ret) 932 goto retry_conn_enable; 933 } 934 KUNIT_ASSERT_EQ(test, ret, 0); 935 936 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 937 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 938 939 new_conn_state = drm_atomic_get_connector_state(state, conn); 940 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 941 942 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 943 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 944 945 new_conn_state->max_requested_bpc = 8; 946 947 KUNIT_ASSERT_NE(test, 948 old_conn_state->max_requested_bpc, 949 new_conn_state->max_requested_bpc); 950 951 ret = drm_atomic_check_only(state); 952 KUNIT_ASSERT_EQ(test, ret, 0); 953 954 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 955 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 956 957 new_conn_state = drm_atomic_get_new_connector_state(state, conn); 958 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 959 960 KUNIT_ASSERT_NE(test, 961 old_conn_state->hdmi.output_bpc, 962 new_conn_state->hdmi.output_bpc); 963 964 crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 965 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 966 KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed); 967 968 drm_modeset_drop_locks(&ctx); 969 drm_modeset_acquire_fini(&ctx); 970 } 971 972 /* 973 * Test that if we set the output bpc property to the same value, we 974 * don't trigger a mode change on the connector's CRTC and leave the 975 * connector unaffected. 976 */ 977 static void drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test) 978 { 979 struct drm_atomic_helper_connector_hdmi_priv *priv; 980 struct drm_modeset_acquire_ctx ctx; 981 struct drm_connector_state *old_conn_state; 982 struct drm_connector_state *new_conn_state; 983 struct drm_crtc_state *crtc_state; 984 struct drm_atomic_state *state; 985 struct drm_display_mode *preferred; 986 struct drm_connector *conn; 987 struct drm_device *drm; 988 struct drm_crtc *crtc; 989 int ret; 990 991 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 992 BIT(HDMI_COLORSPACE_RGB), 993 10, 994 &dummy_connector_hdmi_funcs, 995 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); 996 KUNIT_ASSERT_NOT_NULL(test, priv); 997 998 drm = &priv->drm; 999 crtc = priv->crtc; 1000 conn = &priv->connector; 1001 preferred = find_preferred_mode(conn); 1002 KUNIT_ASSERT_NOT_NULL(test, preferred); 1003 1004 drm_modeset_acquire_init(&ctx, 0); 1005 1006 retry_conn_enable: 1007 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1008 crtc, conn, 1009 preferred, 1010 &ctx); 1011 if (ret == -EDEADLK) { 1012 ret = drm_modeset_backoff(&ctx); 1013 if (!ret) 1014 goto retry_conn_enable; 1015 } 1016 KUNIT_ASSERT_EQ(test, ret, 0); 1017 1018 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 1019 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 1020 1021 new_conn_state = drm_atomic_get_connector_state(state, conn); 1022 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 1023 1024 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 1025 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 1026 1027 KUNIT_ASSERT_EQ(test, 1028 new_conn_state->hdmi.output_bpc, 1029 old_conn_state->hdmi.output_bpc); 1030 1031 ret = drm_atomic_check_only(state); 1032 KUNIT_ASSERT_EQ(test, ret, 0); 1033 1034 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 1035 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 1036 1037 new_conn_state = drm_atomic_get_new_connector_state(state, conn); 1038 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 1039 1040 KUNIT_EXPECT_EQ(test, 1041 old_conn_state->hdmi.output_bpc, 1042 new_conn_state->hdmi.output_bpc); 1043 1044 crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 1045 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 1046 KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed); 1047 1048 drm_modeset_drop_locks(&ctx); 1049 drm_modeset_acquire_fini(&ctx); 1050 } 1051 1052 /* 1053 * Test that if we have an HDMI connector but a !HDMI display, we always 1054 * output RGB with 8 bpc. 1055 */ 1056 static void drm_test_check_output_bpc_dvi(struct kunit *test) 1057 { 1058 struct drm_atomic_helper_connector_hdmi_priv *priv; 1059 struct drm_modeset_acquire_ctx ctx; 1060 struct drm_connector_state *conn_state; 1061 struct drm_display_info *info; 1062 struct drm_display_mode *preferred; 1063 struct drm_connector *conn; 1064 struct drm_device *drm; 1065 struct drm_crtc *crtc; 1066 int ret; 1067 1068 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1069 BIT(HDMI_COLORSPACE_RGB) | 1070 BIT(HDMI_COLORSPACE_YUV422) | 1071 BIT(HDMI_COLORSPACE_YUV444), 1072 12, 1073 &dummy_connector_hdmi_funcs, 1074 test_edid_dvi_1080p); 1075 KUNIT_ASSERT_NOT_NULL(test, priv); 1076 1077 drm = &priv->drm; 1078 crtc = priv->crtc; 1079 conn = &priv->connector; 1080 info = &conn->display_info; 1081 KUNIT_ASSERT_FALSE(test, info->is_hdmi); 1082 1083 preferred = find_preferred_mode(conn); 1084 KUNIT_ASSERT_NOT_NULL(test, preferred); 1085 1086 drm_modeset_acquire_init(&ctx, 0); 1087 1088 retry_conn_enable: 1089 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1090 crtc, conn, 1091 preferred, 1092 &ctx); 1093 if (ret == -EDEADLK) { 1094 ret = drm_modeset_backoff(&ctx); 1095 if (!ret) 1096 goto retry_conn_enable; 1097 } 1098 KUNIT_ASSERT_EQ(test, ret, 0); 1099 1100 conn_state = conn->state; 1101 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1102 1103 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 1104 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1105 1106 drm_modeset_drop_locks(&ctx); 1107 drm_modeset_acquire_fini(&ctx); 1108 } 1109 1110 /* 1111 * Test that when doing a commit which would use RGB 8bpc, the TMDS 1112 * clock rate stored in the connector state is equal to the mode clock 1113 */ 1114 static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test) 1115 { 1116 struct drm_atomic_helper_connector_hdmi_priv *priv; 1117 struct drm_modeset_acquire_ctx ctx; 1118 struct drm_connector_state *conn_state; 1119 struct drm_display_mode *preferred; 1120 struct drm_connector *conn; 1121 struct drm_device *drm; 1122 struct drm_crtc *crtc; 1123 int ret; 1124 1125 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1126 BIT(HDMI_COLORSPACE_RGB), 1127 8, 1128 &dummy_connector_hdmi_funcs, 1129 test_edid_hdmi_1080p_rgb_max_200mhz); 1130 KUNIT_ASSERT_NOT_NULL(test, priv); 1131 1132 drm = &priv->drm; 1133 crtc = priv->crtc; 1134 conn = &priv->connector; 1135 preferred = find_preferred_mode(conn); 1136 KUNIT_ASSERT_NOT_NULL(test, preferred); 1137 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1138 1139 drm_modeset_acquire_init(&ctx, 0); 1140 1141 retry_conn_enable: 1142 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1143 crtc, conn, 1144 preferred, 1145 &ctx); 1146 if (ret == -EDEADLK) { 1147 ret = drm_modeset_backoff(&ctx); 1148 if (!ret) 1149 goto retry_conn_enable; 1150 } 1151 KUNIT_ASSERT_EQ(test, ret, 0); 1152 1153 conn_state = conn->state; 1154 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1155 1156 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 8); 1157 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1158 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1000); 1159 1160 drm_modeset_drop_locks(&ctx); 1161 drm_modeset_acquire_fini(&ctx); 1162 } 1163 1164 /* 1165 * Test that when doing a commit which would use RGB 10bpc, the TMDS 1166 * clock rate stored in the connector state is equal to 1.25 times the 1167 * mode pixel clock 1168 */ 1169 static void drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit *test) 1170 { 1171 struct drm_atomic_helper_connector_hdmi_priv *priv; 1172 struct drm_modeset_acquire_ctx ctx; 1173 struct drm_connector_state *conn_state; 1174 struct drm_display_mode *preferred; 1175 struct drm_connector *conn; 1176 struct drm_device *drm; 1177 struct drm_crtc *crtc; 1178 int ret; 1179 1180 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1181 BIT(HDMI_COLORSPACE_RGB), 1182 10, 1183 &dummy_connector_hdmi_funcs, 1184 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz); 1185 KUNIT_ASSERT_NOT_NULL(test, priv); 1186 1187 drm = &priv->drm; 1188 crtc = priv->crtc; 1189 conn = &priv->connector; 1190 preferred = find_preferred_mode(conn); 1191 KUNIT_ASSERT_NOT_NULL(test, preferred); 1192 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1193 1194 drm_modeset_acquire_init(&ctx, 0); 1195 1196 retry_conn_enable: 1197 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1198 crtc, conn, 1199 preferred, 1200 &ctx); 1201 if (ret == -EDEADLK) { 1202 ret = drm_modeset_backoff(&ctx); 1203 if (!ret) 1204 goto retry_conn_enable; 1205 } 1206 KUNIT_ASSERT_EQ(test, ret, 0); 1207 1208 conn_state = conn->state; 1209 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1210 1211 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 10); 1212 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1213 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250); 1214 1215 drm_modeset_drop_locks(&ctx); 1216 drm_modeset_acquire_fini(&ctx); 1217 } 1218 1219 /* 1220 * Test that when doing a commit which would use RGB 12bpc, the TMDS 1221 * clock rate stored in the connector state is equal to 1.5 times the 1222 * mode pixel clock 1223 */ 1224 static void drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test) 1225 { 1226 struct drm_atomic_helper_connector_hdmi_priv *priv; 1227 struct drm_modeset_acquire_ctx ctx; 1228 struct drm_connector_state *conn_state; 1229 struct drm_display_mode *preferred; 1230 struct drm_connector *conn; 1231 struct drm_device *drm; 1232 struct drm_crtc *crtc; 1233 int ret; 1234 1235 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1236 BIT(HDMI_COLORSPACE_RGB), 1237 12, 1238 &dummy_connector_hdmi_funcs, 1239 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz); 1240 KUNIT_ASSERT_NOT_NULL(test, priv); 1241 1242 drm = &priv->drm; 1243 crtc = priv->crtc; 1244 conn = &priv->connector; 1245 preferred = find_preferred_mode(conn); 1246 KUNIT_ASSERT_NOT_NULL(test, preferred); 1247 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1248 1249 drm_modeset_acquire_init(&ctx, 0); 1250 1251 retry_conn_enable: 1252 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1253 crtc, conn, 1254 preferred, 1255 &ctx); 1256 if (ret == -EDEADLK) { 1257 ret = drm_modeset_backoff(&ctx); 1258 if (!ret) 1259 goto retry_conn_enable; 1260 } 1261 KUNIT_ASSERT_EQ(test, ret, 0); 1262 1263 conn_state = conn->state; 1264 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1265 1266 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 12); 1267 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1268 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1500); 1269 1270 drm_modeset_drop_locks(&ctx); 1271 drm_modeset_acquire_fini(&ctx); 1272 } 1273 1274 /* 1275 * Test that if we filter a rate through our hook, it's indeed rejected 1276 * by the whole atomic_check logic. 1277 * 1278 * We do so by first doing a commit on the pipeline to make sure that it 1279 * works, change the HDMI helpers pointer, and then try the same commit 1280 * again to see if it fails as it should. 1281 */ 1282 static void drm_test_check_hdmi_funcs_reject_rate(struct kunit *test) 1283 { 1284 struct drm_atomic_helper_connector_hdmi_priv *priv; 1285 struct drm_modeset_acquire_ctx ctx; 1286 struct drm_atomic_state *state; 1287 struct drm_display_mode *preferred; 1288 struct drm_crtc_state *crtc_state; 1289 struct drm_connector *conn; 1290 struct drm_device *drm; 1291 struct drm_crtc *crtc; 1292 int ret; 1293 1294 priv = drm_kunit_helper_connector_hdmi_init(test, 1295 BIT(HDMI_COLORSPACE_RGB), 1296 8); 1297 KUNIT_ASSERT_NOT_NULL(test, priv); 1298 1299 drm = &priv->drm; 1300 crtc = priv->crtc; 1301 conn = &priv->connector; 1302 1303 preferred = find_preferred_mode(conn); 1304 KUNIT_ASSERT_NOT_NULL(test, preferred); 1305 1306 drm_modeset_acquire_init(&ctx, 0); 1307 1308 retry_conn_enable: 1309 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1310 crtc, conn, 1311 preferred, 1312 &ctx); 1313 if (ret == -EDEADLK) { 1314 ret = drm_modeset_backoff(&ctx); 1315 if (!ret) 1316 goto retry_conn_enable; 1317 } 1318 KUNIT_ASSERT_EQ(test, ret, 0); 1319 1320 /* You shouldn't be doing that at home. */ 1321 conn->hdmi.funcs = &reject_connector_hdmi_funcs; 1322 1323 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 1324 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 1325 1326 crtc_state = drm_atomic_get_crtc_state(state, crtc); 1327 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 1328 1329 crtc_state->connectors_changed = true; 1330 1331 ret = drm_atomic_check_only(state); 1332 KUNIT_EXPECT_LT(test, ret, 0); 1333 1334 drm_modeset_drop_locks(&ctx); 1335 drm_modeset_acquire_fini(&ctx); 1336 } 1337 1338 /* 1339 * Test that if: 1340 * - We have an HDMI connector supporting RGB only 1341 * - The chosen mode has a TMDS character rate higher than the display 1342 * supports in RGB/12bpc 1343 * - The chosen mode has a TMDS character rate lower than the display 1344 * supports in RGB/10bpc. 1345 * 1346 * Then we will pick the latter, and the computed TMDS character rate 1347 * will be equal to 1.25 times the mode pixel clock. 1348 */ 1349 static void drm_test_check_max_tmds_rate_bpc_fallback_rgb(struct kunit *test) 1350 { 1351 struct drm_atomic_helper_connector_hdmi_priv *priv; 1352 struct drm_modeset_acquire_ctx ctx; 1353 struct drm_connector_state *conn_state; 1354 struct drm_display_info *info; 1355 struct drm_display_mode *preferred; 1356 unsigned long long rate; 1357 struct drm_connector *conn; 1358 struct drm_device *drm; 1359 struct drm_crtc *crtc; 1360 int ret; 1361 1362 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1363 BIT(HDMI_COLORSPACE_RGB), 1364 12, 1365 &dummy_connector_hdmi_funcs, 1366 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); 1367 KUNIT_ASSERT_NOT_NULL(test, priv); 1368 1369 drm = &priv->drm; 1370 crtc = priv->crtc; 1371 conn = &priv->connector; 1372 info = &conn->display_info; 1373 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1374 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1375 1376 preferred = find_preferred_mode(conn); 1377 KUNIT_ASSERT_NOT_NULL(test, preferred); 1378 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1379 1380 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1381 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1382 1383 rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); 1384 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1385 1386 drm_modeset_acquire_init(&ctx, 0); 1387 1388 retry_conn_enable: 1389 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1390 crtc, conn, 1391 preferred, 1392 &ctx); 1393 if (ret == -EDEADLK) { 1394 ret = drm_modeset_backoff(&ctx); 1395 if (!ret) 1396 goto retry_conn_enable; 1397 } 1398 KUNIT_EXPECT_EQ(test, ret, 0); 1399 1400 conn_state = conn->state; 1401 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1402 1403 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); 1404 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1405 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250); 1406 1407 drm_modeset_drop_locks(&ctx); 1408 drm_modeset_acquire_fini(&ctx); 1409 } 1410 1411 /* 1412 * Test that if: 1413 * - We have an HDMI connector and a display supporting both RGB and YUV420 1414 * - The chosen mode can be supported in YUV420 output format only 1415 * - The chosen mode has a TMDS character rate higher than the display 1416 * supports in YUV420/12bpc 1417 * - The chosen mode has a TMDS character rate lower than the display 1418 * supports in YUV420/10bpc. 1419 * 1420 * Then we will pick the latter, and the computed TMDS character rate 1421 * will be equal to 1.25 * 0.5 times the mode pixel clock. 1422 */ 1423 static void drm_test_check_max_tmds_rate_bpc_fallback_yuv420(struct kunit *test) 1424 { 1425 struct drm_atomic_helper_connector_hdmi_priv *priv; 1426 struct drm_modeset_acquire_ctx ctx; 1427 struct drm_connector_state *conn_state; 1428 struct drm_display_info *info; 1429 struct drm_display_mode *yuv420_only_mode; 1430 unsigned long long rate; 1431 struct drm_connector *conn; 1432 struct drm_device *drm; 1433 struct drm_crtc *crtc; 1434 int ret; 1435 1436 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1437 BIT(HDMI_COLORSPACE_RGB) | 1438 BIT(HDMI_COLORSPACE_YUV420), 1439 12, 1440 &dummy_connector_hdmi_funcs, 1441 test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); 1442 KUNIT_ASSERT_NOT_NULL(test, priv); 1443 1444 drm = &priv->drm; 1445 crtc = priv->crtc; 1446 conn = &priv->connector; 1447 info = &conn->display_info; 1448 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1449 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1450 KUNIT_ASSERT_TRUE(test, conn->ycbcr_420_allowed); 1451 1452 yuv420_only_mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95); 1453 KUNIT_ASSERT_NOT_NULL(test, yuv420_only_mode); 1454 KUNIT_ASSERT_TRUE(test, drm_mode_is_420_only(info, yuv420_only_mode)); 1455 1456 rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 12, HDMI_COLORSPACE_YUV420); 1457 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1458 1459 rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 10, HDMI_COLORSPACE_YUV420); 1460 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1461 1462 drm_modeset_acquire_init(&ctx, 0); 1463 1464 retry_conn_enable: 1465 ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, 1466 yuv420_only_mode, &ctx); 1467 if (ret == -EDEADLK) { 1468 ret = drm_modeset_backoff(&ctx); 1469 if (!ret) 1470 goto retry_conn_enable; 1471 } 1472 KUNIT_EXPECT_EQ(test, ret, 0); 1473 1474 conn_state = conn->state; 1475 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1476 1477 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); 1478 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420); 1479 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, yuv420_only_mode->clock * 625); 1480 1481 drm_modeset_drop_locks(&ctx); 1482 drm_modeset_acquire_fini(&ctx); 1483 } 1484 1485 /* 1486 * Test that if: 1487 * - We have an HDMI connector supporting both RGB and YUV422 and up to 1488 * 12 bpc 1489 * - The chosen mode has a TMDS character rate higher than the display 1490 * supports in RGB/12bpc but lower than the display supports in 1491 * RGB/10bpc 1492 * - The chosen mode has a TMDS character rate lower than the display 1493 * supports in YUV422/12bpc. 1494 * 1495 * Then we will prefer to keep the RGB format with a lower bpc over 1496 * picking YUV422. 1497 */ 1498 static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422(struct kunit *test) 1499 { 1500 struct drm_atomic_helper_connector_hdmi_priv *priv; 1501 struct drm_modeset_acquire_ctx ctx; 1502 struct drm_connector_state *conn_state; 1503 struct drm_display_info *info; 1504 struct drm_display_mode *preferred; 1505 unsigned long long rate; 1506 struct drm_connector *conn; 1507 struct drm_device *drm; 1508 struct drm_crtc *crtc; 1509 int ret; 1510 1511 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1512 BIT(HDMI_COLORSPACE_RGB) | 1513 BIT(HDMI_COLORSPACE_YUV422) | 1514 BIT(HDMI_COLORSPACE_YUV444), 1515 12, 1516 &dummy_connector_hdmi_funcs, 1517 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); 1518 KUNIT_ASSERT_NOT_NULL(test, priv); 1519 1520 drm = &priv->drm; 1521 crtc = priv->crtc; 1522 conn = &priv->connector; 1523 info = &conn->display_info; 1524 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1525 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1526 1527 preferred = find_preferred_mode(conn); 1528 KUNIT_ASSERT_NOT_NULL(test, preferred); 1529 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1530 1531 rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); 1532 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1533 1534 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1535 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1536 1537 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); 1538 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1539 1540 drm_modeset_acquire_init(&ctx, 0); 1541 1542 retry_conn_enable: 1543 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1544 crtc, conn, 1545 preferred, 1546 &ctx); 1547 if (ret == -EDEADLK) { 1548 ret = drm_modeset_backoff(&ctx); 1549 if (!ret) 1550 goto retry_conn_enable; 1551 } 1552 KUNIT_EXPECT_EQ(test, ret, 0); 1553 1554 conn_state = conn->state; 1555 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1556 1557 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); 1558 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1559 1560 drm_modeset_drop_locks(&ctx); 1561 drm_modeset_acquire_fini(&ctx); 1562 } 1563 1564 /* 1565 * Test that if: 1566 * - We have an HDMI connector supporting both RGB and YUV420 and up to 1567 * 12 bpc 1568 * - The chosen mode has a TMDS character rate higher than the display 1569 * supports in RGB/10bpc but lower than the display supports in 1570 * RGB/8bpc 1571 * - The chosen mode has a TMDS character rate lower than the display 1572 * supports in YUV420/12bpc. 1573 * 1574 * Then we will prefer to keep the RGB format with a lower bpc over 1575 * picking YUV420. 1576 */ 1577 static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420(struct kunit *test) 1578 { 1579 struct drm_atomic_helper_connector_hdmi_priv *priv; 1580 struct drm_modeset_acquire_ctx ctx; 1581 struct drm_connector_state *conn_state; 1582 struct drm_display_info *info; 1583 struct drm_display_mode *preferred; 1584 unsigned long long rate; 1585 struct drm_connector *conn; 1586 struct drm_device *drm; 1587 struct drm_crtc *crtc; 1588 int ret; 1589 1590 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1591 BIT(HDMI_COLORSPACE_RGB) | 1592 BIT(HDMI_COLORSPACE_YUV420), 1593 12, 1594 &dummy_connector_hdmi_funcs, 1595 test_edid_hdmi_4k_rgb_yuv420_dc_max_340mhz); 1596 KUNIT_ASSERT_NOT_NULL(test, priv); 1597 1598 drm = &priv->drm; 1599 crtc = priv->crtc; 1600 conn = &priv->connector; 1601 info = &conn->display_info; 1602 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1603 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1604 KUNIT_ASSERT_TRUE(test, conn->ycbcr_420_allowed); 1605 1606 preferred = find_preferred_mode(conn); 1607 KUNIT_ASSERT_NOT_NULL(test, preferred); 1608 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1609 KUNIT_ASSERT_TRUE(test, drm_mode_is_420_also(info, preferred)); 1610 1611 rate = drm_hdmi_compute_mode_clock(preferred, 8, HDMI_COLORSPACE_RGB); 1612 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1613 1614 rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); 1615 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1616 1617 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV420); 1618 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1619 1620 drm_modeset_acquire_init(&ctx, 0); 1621 1622 retry_conn_enable: 1623 ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, 1624 preferred, &ctx); 1625 if (ret == -EDEADLK) { 1626 ret = drm_modeset_backoff(&ctx); 1627 if (!ret) 1628 goto retry_conn_enable; 1629 } 1630 KUNIT_EXPECT_EQ(test, ret, 0); 1631 1632 conn_state = conn->state; 1633 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1634 1635 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 1636 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1637 1638 drm_modeset_drop_locks(&ctx); 1639 drm_modeset_acquire_fini(&ctx); 1640 } 1641 1642 /* 1643 * Test that if a driver supports only RGB, but the chosen mode can be 1644 * supported by the screen only in YUV420 output format, we end up with 1645 * unsuccessful fallback attempts. 1646 */ 1647 static void drm_test_check_driver_unsupported_fallback_yuv420(struct kunit *test) 1648 { 1649 struct drm_atomic_helper_connector_hdmi_priv *priv; 1650 struct drm_modeset_acquire_ctx ctx; 1651 struct drm_connector_state *conn_state; 1652 struct drm_crtc_state *crtc_state; 1653 struct drm_atomic_state *state; 1654 struct drm_display_info *info; 1655 struct drm_display_mode *preferred, *yuv420_only_mode; 1656 struct drm_connector *conn; 1657 struct drm_device *drm; 1658 struct drm_crtc *crtc; 1659 int ret; 1660 1661 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1662 BIT(HDMI_COLORSPACE_RGB), 1663 12, 1664 &dummy_connector_hdmi_funcs, 1665 test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); 1666 KUNIT_ASSERT_NOT_NULL(test, priv); 1667 1668 drm = &priv->drm; 1669 crtc = priv->crtc; 1670 conn = &priv->connector; 1671 info = &conn->display_info; 1672 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1673 KUNIT_ASSERT_FALSE(test, conn->ycbcr_420_allowed); 1674 1675 preferred = find_preferred_mode(conn); 1676 KUNIT_ASSERT_NOT_NULL(test, preferred); 1677 KUNIT_ASSERT_FALSE(test, drm_mode_is_420_also(info, preferred)); 1678 1679 yuv420_only_mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95); 1680 KUNIT_ASSERT_NOT_NULL(test, yuv420_only_mode); 1681 KUNIT_ASSERT_TRUE(test, drm_mode_is_420_only(info, yuv420_only_mode)); 1682 1683 drm_modeset_acquire_init(&ctx, 0); 1684 1685 retry_conn_enable: 1686 ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, 1687 preferred, &ctx); 1688 if (ret == -EDEADLK) { 1689 ret = drm_modeset_backoff(&ctx); 1690 if (!ret) 1691 goto retry_conn_enable; 1692 } 1693 KUNIT_EXPECT_EQ(test, ret, 0); 1694 1695 conn_state = conn->state; 1696 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1697 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1698 1699 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 1700 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 1701 1702 retry_crtc_state: 1703 crtc_state = drm_atomic_get_crtc_state(state, crtc); 1704 if (PTR_ERR(crtc_state) == -EDEADLK) { 1705 drm_atomic_state_clear(state); 1706 ret = drm_modeset_backoff(&ctx); 1707 if (!ret) 1708 goto retry_crtc_state; 1709 } 1710 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 1711 1712 ret = drm_atomic_set_mode_for_crtc(crtc_state, yuv420_only_mode); 1713 KUNIT_EXPECT_EQ(test, ret, 0); 1714 1715 ret = drm_atomic_check_only(state); 1716 if (ret == -EDEADLK) { 1717 drm_atomic_state_clear(state); 1718 ret = drm_modeset_backoff(&ctx); 1719 if (!ret) 1720 goto retry_crtc_state; 1721 } 1722 KUNIT_ASSERT_LT(test, ret, 0); 1723 1724 drm_modeset_drop_locks(&ctx); 1725 drm_modeset_acquire_fini(&ctx); 1726 } 1727 1728 /* 1729 * Test that if a driver and screen supports RGB and YUV formats, and we 1730 * try to set the VIC 1 mode, we end up with 8bpc RGB even if we could 1731 * have had a higher bpc. 1732 */ 1733 static void drm_test_check_output_bpc_format_vic_1(struct kunit *test) 1734 { 1735 struct drm_atomic_helper_connector_hdmi_priv *priv; 1736 struct drm_modeset_acquire_ctx ctx; 1737 struct drm_connector_state *conn_state; 1738 struct drm_display_info *info; 1739 struct drm_display_mode *mode; 1740 unsigned long long rate; 1741 struct drm_connector *conn; 1742 struct drm_device *drm; 1743 struct drm_crtc *crtc; 1744 int ret; 1745 1746 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1747 BIT(HDMI_COLORSPACE_RGB) | 1748 BIT(HDMI_COLORSPACE_YUV422) | 1749 BIT(HDMI_COLORSPACE_YUV444), 1750 12, 1751 &dummy_connector_hdmi_funcs, 1752 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); 1753 KUNIT_ASSERT_NOT_NULL(test, priv); 1754 1755 drm = &priv->drm; 1756 conn = &priv->connector; 1757 info = &conn->display_info; 1758 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1759 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1760 1761 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); 1762 KUNIT_ASSERT_NOT_NULL(test, mode); 1763 1764 /* 1765 * NOTE: We can't use drm_hdmi_compute_mode_clock() 1766 * here because we're trying to get the rate of an invalid 1767 * configuration. 1768 * 1769 * Thus, we have to calculate the rate by hand. 1770 */ 1771 rate = mode->clock * 1500; 1772 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1773 1774 drm_modeset_acquire_init(&ctx, 0); 1775 1776 crtc = priv->crtc; 1777 1778 retry_conn_enable: 1779 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1780 crtc, conn, 1781 mode, 1782 &ctx); 1783 if (ret == -EDEADLK) { 1784 ret = drm_modeset_backoff(&ctx); 1785 if (!ret) 1786 goto retry_conn_enable; 1787 } 1788 KUNIT_EXPECT_EQ(test, ret, 0); 1789 1790 conn_state = conn->state; 1791 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1792 1793 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 1794 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1795 1796 drm_modeset_drop_locks(&ctx); 1797 drm_modeset_acquire_fini(&ctx); 1798 } 1799 1800 /* 1801 * Test that if a driver supports only RGB but the screen also supports 1802 * YUV formats, we only end up with an RGB format. 1803 */ 1804 static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test) 1805 { 1806 struct drm_atomic_helper_connector_hdmi_priv *priv; 1807 struct drm_modeset_acquire_ctx ctx; 1808 struct drm_connector_state *conn_state; 1809 struct drm_display_info *info; 1810 struct drm_display_mode *preferred; 1811 unsigned long long rate; 1812 struct drm_connector *conn; 1813 struct drm_device *drm; 1814 struct drm_crtc *crtc; 1815 int ret; 1816 1817 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1818 BIT(HDMI_COLORSPACE_RGB), 1819 12, 1820 &dummy_connector_hdmi_funcs, 1821 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); 1822 KUNIT_ASSERT_NOT_NULL(test, priv); 1823 1824 drm = &priv->drm; 1825 crtc = priv->crtc; 1826 conn = &priv->connector; 1827 info = &conn->display_info; 1828 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1829 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1830 1831 preferred = find_preferred_mode(conn); 1832 KUNIT_ASSERT_NOT_NULL(test, preferred); 1833 1834 /* 1835 * We're making sure that YUV422 would be the preferred option 1836 * here: we're always favouring higher bpc, we can't have RGB 1837 * because the TMDS character rate exceeds the maximum supported 1838 * by the display, and YUV422 works for that display. 1839 * 1840 * But since the driver only supports RGB, we should fallback to 1841 * a lower bpc with RGB. 1842 */ 1843 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1844 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1845 1846 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); 1847 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1848 1849 drm_modeset_acquire_init(&ctx, 0); 1850 1851 retry_conn_enable: 1852 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1853 crtc, conn, 1854 preferred, 1855 &ctx); 1856 if (ret == -EDEADLK) { 1857 ret = drm_modeset_backoff(&ctx); 1858 if (!ret) 1859 goto retry_conn_enable; 1860 } 1861 KUNIT_EXPECT_EQ(test, ret, 0); 1862 1863 conn_state = conn->state; 1864 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1865 1866 KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12); 1867 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1868 1869 drm_modeset_drop_locks(&ctx); 1870 drm_modeset_acquire_fini(&ctx); 1871 } 1872 1873 /* 1874 * Test that if a screen supports only RGB but the driver also supports 1875 * YUV formats, we only end up with an RGB format. 1876 */ 1877 static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test) 1878 { 1879 struct drm_atomic_helper_connector_hdmi_priv *priv; 1880 struct drm_modeset_acquire_ctx ctx; 1881 struct drm_connector_state *conn_state; 1882 struct drm_display_info *info; 1883 struct drm_display_mode *preferred; 1884 unsigned long long rate; 1885 struct drm_connector *conn; 1886 struct drm_device *drm; 1887 struct drm_crtc *crtc; 1888 int ret; 1889 1890 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1891 BIT(HDMI_COLORSPACE_RGB) | 1892 BIT(HDMI_COLORSPACE_YUV422) | 1893 BIT(HDMI_COLORSPACE_YUV444), 1894 12, 1895 &dummy_connector_hdmi_funcs, 1896 test_edid_hdmi_1080p_rgb_max_200mhz); 1897 KUNIT_ASSERT_NOT_NULL(test, priv); 1898 1899 drm = &priv->drm; 1900 crtc = priv->crtc; 1901 conn = &priv->connector; 1902 info = &conn->display_info; 1903 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1904 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1905 1906 preferred = find_preferred_mode(conn); 1907 KUNIT_ASSERT_NOT_NULL(test, preferred); 1908 1909 /* 1910 * We're making sure that YUV422 would be the preferred option 1911 * here: we're always favouring higher bpc, we can't have RGB 1912 * because the TMDS character rate exceeds the maximum supported 1913 * by the display, and YUV422 works for that display. 1914 * 1915 * But since the display only supports RGB, we should fallback to 1916 * a lower bpc with RGB. 1917 */ 1918 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1919 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1920 1921 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); 1922 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1923 1924 drm_modeset_acquire_init(&ctx, 0); 1925 1926 retry_conn_enable: 1927 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1928 crtc, conn, 1929 preferred, 1930 &ctx); 1931 if (ret == -EDEADLK) { 1932 ret = drm_modeset_backoff(&ctx); 1933 if (!ret) 1934 goto retry_conn_enable; 1935 } 1936 KUNIT_EXPECT_EQ(test, ret, 0); 1937 1938 conn_state = conn->state; 1939 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1940 1941 KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12); 1942 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1943 1944 drm_modeset_drop_locks(&ctx); 1945 drm_modeset_acquire_fini(&ctx); 1946 } 1947 1948 /* 1949 * Test that if a display supports higher bpc but the driver only 1950 * supports 8 bpc, we only end up with 8 bpc even if we could have had a 1951 * higher bpc. 1952 */ 1953 static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test) 1954 { 1955 struct drm_atomic_helper_connector_hdmi_priv *priv; 1956 struct drm_modeset_acquire_ctx ctx; 1957 struct drm_connector_state *conn_state; 1958 struct drm_display_info *info; 1959 struct drm_display_mode *preferred; 1960 unsigned long long rate; 1961 struct drm_connector *conn; 1962 struct drm_device *drm; 1963 struct drm_crtc *crtc; 1964 int ret; 1965 1966 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1967 BIT(HDMI_COLORSPACE_RGB), 1968 8, 1969 &dummy_connector_hdmi_funcs, 1970 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz); 1971 KUNIT_ASSERT_NOT_NULL(test, priv); 1972 1973 drm = &priv->drm; 1974 crtc = priv->crtc; 1975 conn = &priv->connector; 1976 info = &conn->display_info; 1977 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1978 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1979 1980 preferred = find_preferred_mode(conn); 1981 KUNIT_ASSERT_NOT_NULL(test, preferred); 1982 1983 /* 1984 * We're making sure that we have headroom on the TMDS character 1985 * clock to actually use 12bpc. 1986 */ 1987 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1988 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1989 1990 drm_modeset_acquire_init(&ctx, 0); 1991 1992 retry_conn_enable: 1993 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1994 crtc, conn, 1995 preferred, 1996 &ctx); 1997 if (ret == -EDEADLK) { 1998 ret = drm_modeset_backoff(&ctx); 1999 if (!ret) 2000 goto retry_conn_enable; 2001 } 2002 KUNIT_EXPECT_EQ(test, ret, 0); 2003 2004 conn_state = conn->state; 2005 KUNIT_ASSERT_NOT_NULL(test, conn_state); 2006 2007 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 2008 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 2009 2010 drm_modeset_drop_locks(&ctx); 2011 drm_modeset_acquire_fini(&ctx); 2012 } 2013 2014 /* 2015 * Test that if a driver supports higher bpc but the display only 2016 * supports 8 bpc, we only end up with 8 bpc even if we could have had a 2017 * higher bpc. 2018 */ 2019 static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *test) 2020 { 2021 struct drm_atomic_helper_connector_hdmi_priv *priv; 2022 struct drm_modeset_acquire_ctx ctx; 2023 struct drm_connector_state *conn_state; 2024 struct drm_display_info *info; 2025 struct drm_display_mode *preferred; 2026 unsigned long long rate; 2027 struct drm_connector *conn; 2028 struct drm_device *drm; 2029 struct drm_crtc *crtc; 2030 int ret; 2031 2032 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2033 BIT(HDMI_COLORSPACE_RGB) | 2034 BIT(HDMI_COLORSPACE_YUV422) | 2035 BIT(HDMI_COLORSPACE_YUV444), 2036 12, 2037 &dummy_connector_hdmi_funcs, 2038 test_edid_hdmi_1080p_rgb_max_340mhz); 2039 KUNIT_ASSERT_NOT_NULL(test, priv); 2040 2041 drm = &priv->drm; 2042 crtc = priv->crtc; 2043 conn = &priv->connector; 2044 info = &conn->display_info; 2045 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 2046 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 2047 2048 preferred = find_preferred_mode(conn); 2049 KUNIT_ASSERT_NOT_NULL(test, preferred); 2050 2051 /* 2052 * We're making sure that we have headroom on the TMDS character 2053 * clock to actually use 12bpc. 2054 */ 2055 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 2056 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 2057 2058 drm_modeset_acquire_init(&ctx, 0); 2059 2060 retry_conn_enable: 2061 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 2062 crtc, conn, 2063 preferred, 2064 &ctx); 2065 if (ret == -EDEADLK) { 2066 ret = drm_modeset_backoff(&ctx); 2067 if (!ret) 2068 goto retry_conn_enable; 2069 } 2070 KUNIT_EXPECT_EQ(test, ret, 0); 2071 2072 conn_state = conn->state; 2073 KUNIT_ASSERT_NOT_NULL(test, conn_state); 2074 2075 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 2076 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 2077 2078 drm_modeset_drop_locks(&ctx); 2079 drm_modeset_acquire_fini(&ctx); 2080 } 2081 2082 /* Test that atomic check succeeds when disabling a connector. */ 2083 static void drm_test_check_disable_connector(struct kunit *test) 2084 { 2085 struct drm_atomic_helper_connector_hdmi_priv *priv; 2086 struct drm_modeset_acquire_ctx ctx; 2087 struct drm_connector_state *conn_state; 2088 struct drm_crtc_state *crtc_state; 2089 struct drm_atomic_state *state; 2090 struct drm_display_mode *preferred; 2091 struct drm_connector *conn; 2092 struct drm_device *drm; 2093 struct drm_crtc *crtc; 2094 int ret; 2095 2096 priv = drm_kunit_helper_connector_hdmi_init(test, 2097 BIT(HDMI_COLORSPACE_RGB), 2098 8); 2099 KUNIT_ASSERT_NOT_NULL(test, priv); 2100 2101 drm_modeset_acquire_init(&ctx, 0); 2102 2103 conn = &priv->connector; 2104 preferred = find_preferred_mode(conn); 2105 KUNIT_ASSERT_NOT_NULL(test, preferred); 2106 2107 drm = &priv->drm; 2108 crtc = priv->crtc; 2109 2110 retry_conn_enable: 2111 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 2112 crtc, conn, 2113 preferred, 2114 &ctx); 2115 if (ret == -EDEADLK) { 2116 ret = drm_modeset_backoff(&ctx); 2117 if (!ret) 2118 goto retry_conn_enable; 2119 } 2120 KUNIT_ASSERT_EQ(test, ret, 0); 2121 2122 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 2123 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 2124 2125 crtc_state = drm_atomic_get_crtc_state(state, crtc); 2126 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 2127 2128 crtc_state->active = false; 2129 ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); 2130 KUNIT_EXPECT_EQ(test, ret, 0); 2131 2132 conn_state = drm_atomic_get_connector_state(state, conn); 2133 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 2134 2135 ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); 2136 KUNIT_EXPECT_EQ(test, ret, 0); 2137 2138 ret = drm_atomic_check_only(state); 2139 KUNIT_ASSERT_EQ(test, ret, 0); 2140 2141 drm_modeset_drop_locks(&ctx); 2142 drm_modeset_acquire_fini(&ctx); 2143 } 2144 2145 static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = { 2146 KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode), 2147 KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode_vic_1), 2148 KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode), 2149 KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode_vic_1), 2150 KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode), 2151 KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode_vic_1), 2152 KUNIT_CASE_PARAM(drm_test_check_broadcast_rgb_cea_mode_yuv420, 2153 check_broadcast_rgb_cea_mode_yuv420_gen_params), 2154 KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_changed), 2155 KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_not_changed), 2156 KUNIT_CASE(drm_test_check_disable_connector), 2157 KUNIT_CASE(drm_test_check_hdmi_funcs_reject_rate), 2158 KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_rgb), 2159 KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_yuv420), 2160 KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422), 2161 KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420), 2162 KUNIT_CASE(drm_test_check_driver_unsupported_fallback_yuv420), 2163 KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_changed), 2164 KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_not_changed), 2165 KUNIT_CASE(drm_test_check_output_bpc_dvi), 2166 KUNIT_CASE(drm_test_check_output_bpc_format_vic_1), 2167 KUNIT_CASE(drm_test_check_output_bpc_format_display_8bpc_only), 2168 KUNIT_CASE(drm_test_check_output_bpc_format_display_rgb_only), 2169 KUNIT_CASE(drm_test_check_output_bpc_format_driver_8bpc_only), 2170 KUNIT_CASE(drm_test_check_output_bpc_format_driver_rgb_only), 2171 KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_8bpc), 2172 KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_10bpc), 2173 KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_12bpc), 2174 /* 2175 * TODO: We should have tests to check that a change in the 2176 * format triggers a CRTC mode change just like we do for the 2177 * RGB Quantization and BPC. 2178 * 2179 * However, we don't have any way to control which format gets 2180 * picked up aside from changing the BPC or mode which would 2181 * already trigger a mode change. 2182 */ 2183 { } 2184 }; 2185 2186 static struct kunit_suite drm_atomic_helper_connector_hdmi_check_test_suite = { 2187 .name = "drm_atomic_helper_connector_hdmi_check", 2188 .test_cases = drm_atomic_helper_connector_hdmi_check_tests, 2189 }; 2190 2191 /* 2192 * Test that the value of the Broadcast RGB property out of reset is set 2193 * to auto. 2194 */ 2195 static void drm_test_check_broadcast_rgb_value(struct kunit *test) 2196 { 2197 struct drm_atomic_helper_connector_hdmi_priv *priv; 2198 struct drm_connector_state *conn_state; 2199 struct drm_connector *conn; 2200 2201 priv = drm_kunit_helper_connector_hdmi_init(test, 2202 BIT(HDMI_COLORSPACE_RGB), 2203 8); 2204 KUNIT_ASSERT_NOT_NULL(test, priv); 2205 2206 conn = &priv->connector; 2207 conn_state = conn->state; 2208 KUNIT_EXPECT_EQ(test, conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_AUTO); 2209 } 2210 2211 /* 2212 * Test that if the connector was initialised with a maximum bpc of 8, 2213 * the value of the max_bpc and max_requested_bpc properties out of 2214 * reset are also set to 8, and output_bpc is set to 0 and will be 2215 * filled at atomic_check time. 2216 */ 2217 static void drm_test_check_bpc_8_value(struct kunit *test) 2218 { 2219 struct drm_atomic_helper_connector_hdmi_priv *priv; 2220 struct drm_connector_state *conn_state; 2221 struct drm_connector *conn; 2222 2223 priv = drm_kunit_helper_connector_hdmi_init(test, 2224 BIT(HDMI_COLORSPACE_RGB), 2225 8); 2226 KUNIT_ASSERT_NOT_NULL(test, priv); 2227 2228 conn = &priv->connector; 2229 conn_state = conn->state; 2230 KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 8); 2231 KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 8); 2232 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0); 2233 } 2234 2235 /* 2236 * Test that if the connector was initialised with a maximum bpc of 10, 2237 * the value of the max_bpc and max_requested_bpc properties out of 2238 * reset are also set to 10, and output_bpc is set to 0 and will be 2239 * filled at atomic_check time. 2240 */ 2241 static void drm_test_check_bpc_10_value(struct kunit *test) 2242 { 2243 struct drm_atomic_helper_connector_hdmi_priv *priv; 2244 struct drm_connector_state *conn_state; 2245 struct drm_connector *conn; 2246 2247 priv = drm_kunit_helper_connector_hdmi_init(test, 2248 BIT(HDMI_COLORSPACE_RGB), 2249 10); 2250 KUNIT_ASSERT_NOT_NULL(test, priv); 2251 2252 conn = &priv->connector; 2253 conn_state = conn->state; 2254 KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 10); 2255 KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 10); 2256 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0); 2257 } 2258 2259 /* 2260 * Test that if the connector was initialised with a maximum bpc of 12, 2261 * the value of the max_bpc and max_requested_bpc properties out of 2262 * reset are also set to 12, and output_bpc is set to 0 and will be 2263 * filled at atomic_check time. 2264 */ 2265 static void drm_test_check_bpc_12_value(struct kunit *test) 2266 { 2267 struct drm_atomic_helper_connector_hdmi_priv *priv; 2268 struct drm_connector_state *conn_state; 2269 struct drm_connector *conn; 2270 2271 priv = drm_kunit_helper_connector_hdmi_init(test, 2272 BIT(HDMI_COLORSPACE_RGB), 2273 12); 2274 KUNIT_ASSERT_NOT_NULL(test, priv); 2275 2276 conn = &priv->connector; 2277 conn_state = conn->state; 2278 KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 12); 2279 KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 12); 2280 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0); 2281 } 2282 2283 /* 2284 * Test that the value of the output format property out of reset is set 2285 * to RGB, even if the driver supports more than that. 2286 */ 2287 static void drm_test_check_format_value(struct kunit *test) 2288 { 2289 struct drm_atomic_helper_connector_hdmi_priv *priv; 2290 struct drm_connector_state *conn_state; 2291 struct drm_connector *conn; 2292 2293 priv = drm_kunit_helper_connector_hdmi_init(test, 2294 BIT(HDMI_COLORSPACE_RGB) | 2295 BIT(HDMI_COLORSPACE_YUV422) | 2296 BIT(HDMI_COLORSPACE_YUV444), 2297 8); 2298 KUNIT_ASSERT_NOT_NULL(test, priv); 2299 2300 conn = &priv->connector; 2301 conn_state = conn->state; 2302 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, 0); 2303 } 2304 2305 /* 2306 * Test that the value of the output format property out of reset is set 2307 * to 0, and will be computed at atomic_check time. 2308 */ 2309 static void drm_test_check_tmds_char_value(struct kunit *test) 2310 { 2311 struct drm_atomic_helper_connector_hdmi_priv *priv; 2312 struct drm_connector_state *conn_state; 2313 struct drm_connector *conn; 2314 2315 priv = drm_kunit_helper_connector_hdmi_init(test, 2316 BIT(HDMI_COLORSPACE_RGB) | 2317 BIT(HDMI_COLORSPACE_YUV422) | 2318 BIT(HDMI_COLORSPACE_YUV444), 2319 12); 2320 KUNIT_ASSERT_NOT_NULL(test, priv); 2321 2322 conn = &priv->connector; 2323 conn_state = conn->state; 2324 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, 0); 2325 } 2326 2327 static struct kunit_case drm_atomic_helper_connector_hdmi_reset_tests[] = { 2328 KUNIT_CASE(drm_test_check_broadcast_rgb_value), 2329 KUNIT_CASE(drm_test_check_bpc_8_value), 2330 KUNIT_CASE(drm_test_check_bpc_10_value), 2331 KUNIT_CASE(drm_test_check_bpc_12_value), 2332 KUNIT_CASE(drm_test_check_format_value), 2333 KUNIT_CASE(drm_test_check_tmds_char_value), 2334 { } 2335 }; 2336 2337 static struct kunit_suite drm_atomic_helper_connector_hdmi_reset_test_suite = { 2338 .name = "drm_atomic_helper_connector_hdmi_reset", 2339 .test_cases = drm_atomic_helper_connector_hdmi_reset_tests, 2340 }; 2341 2342 /* 2343 * Test that the default behaviour for drm_hdmi_connector_mode_valid() is not 2344 * to reject any modes. Pass a correct EDID and verify that preferred mode 2345 * matches the expectations (1080p). 2346 */ 2347 static void drm_test_check_mode_valid(struct kunit *test) 2348 { 2349 struct drm_atomic_helper_connector_hdmi_priv *priv; 2350 struct drm_connector *conn; 2351 struct drm_display_mode *preferred; 2352 2353 priv = drm_kunit_helper_connector_hdmi_init(test, 2354 BIT(HDMI_COLORSPACE_RGB), 2355 8); 2356 KUNIT_ASSERT_NOT_NULL(test, priv); 2357 2358 conn = &priv->connector; 2359 preferred = find_preferred_mode(conn); 2360 KUNIT_ASSERT_NOT_NULL(test, preferred); 2361 2362 KUNIT_EXPECT_EQ(test, preferred->hdisplay, 1920); 2363 KUNIT_EXPECT_EQ(test, preferred->vdisplay, 1080); 2364 KUNIT_EXPECT_EQ(test, preferred->clock, 148500); 2365 } 2366 2367 /* 2368 * Test that the drm_hdmi_connector_mode_valid() will reject modes depending on 2369 * the .tmds_char_rate_valid() behaviour. 2370 * Pass a correct EDID and verify that high-rate modes are filtered. 2371 */ 2372 static void drm_test_check_mode_valid_reject_rate(struct kunit *test) 2373 { 2374 struct drm_atomic_helper_connector_hdmi_priv *priv; 2375 struct drm_display_mode *preferred; 2376 2377 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2378 BIT(HDMI_COLORSPACE_RGB), 2379 8, 2380 &reject_100mhz_connector_hdmi_funcs, 2381 test_edid_hdmi_1080p_rgb_max_200mhz); 2382 KUNIT_ASSERT_NOT_NULL(test, priv); 2383 2384 /* 2385 * Unlike the drm_test_check_mode_valid() here 1080p is rejected, but 2386 * 480p is allowed. 2387 */ 2388 preferred = find_preferred_mode(&priv->connector); 2389 KUNIT_ASSERT_NOT_NULL(test, preferred); 2390 KUNIT_EXPECT_EQ(test, preferred->hdisplay, 640); 2391 KUNIT_EXPECT_EQ(test, preferred->vdisplay, 480); 2392 KUNIT_EXPECT_EQ(test, preferred->clock, 25200); 2393 } 2394 2395 /* 2396 * Test that the drm_hdmi_connector_mode_valid() will not mark any modes as 2397 * valid if .tmds_char_rate_valid() rejects all of them. Pass a correct EDID 2398 * and verify that there is no preferred mode and no modes were set for the 2399 * connector. 2400 */ 2401 static void drm_test_check_mode_valid_reject(struct kunit *test) 2402 { 2403 struct drm_atomic_helper_connector_hdmi_priv *priv; 2404 struct drm_connector *conn; 2405 struct drm_display_mode *preferred; 2406 unsigned char no_edid[] = {}; 2407 int ret; 2408 2409 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2410 BIT(HDMI_COLORSPACE_RGB), 2411 8, 2412 &reject_connector_hdmi_funcs, 2413 no_edid); 2414 KUNIT_ASSERT_NOT_NULL(test, priv); 2415 2416 conn = &priv->connector; 2417 2418 /* should reject all modes */ 2419 ret = set_connector_edid(test, conn, 2420 test_edid_hdmi_1080p_rgb_max_200mhz, 2421 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz)); 2422 KUNIT_ASSERT_EQ(test, ret, 0); 2423 2424 preferred = find_preferred_mode(conn); 2425 KUNIT_ASSERT_NULL(test, preferred); 2426 } 2427 2428 /* 2429 * Test that the drm_hdmi_connector_mode_valid() will reject modes that don't 2430 * pass the info.max_tmds_clock filter. Pass crafted EDID and verify that 2431 * high-rate modes are filtered. 2432 */ 2433 static void drm_test_check_mode_valid_reject_max_clock(struct kunit *test) 2434 { 2435 struct drm_atomic_helper_connector_hdmi_priv *priv; 2436 struct drm_connector *conn; 2437 struct drm_display_mode *preferred; 2438 2439 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2440 BIT(HDMI_COLORSPACE_RGB), 2441 8, 2442 &dummy_connector_hdmi_funcs, 2443 test_edid_hdmi_1080p_rgb_max_100mhz); 2444 KUNIT_ASSERT_NOT_NULL(test, priv); 2445 2446 conn = &priv->connector; 2447 KUNIT_ASSERT_EQ(test, conn->display_info.max_tmds_clock, 100 * 1000); 2448 2449 preferred = find_preferred_mode(conn); 2450 KUNIT_ASSERT_NOT_NULL(test, preferred); 2451 KUNIT_EXPECT_EQ(test, preferred->hdisplay, 640); 2452 KUNIT_EXPECT_EQ(test, preferred->vdisplay, 480); 2453 KUNIT_EXPECT_EQ(test, preferred->clock, 25200); 2454 } 2455 2456 static struct kunit_case drm_atomic_helper_connector_hdmi_mode_valid_tests[] = { 2457 KUNIT_CASE(drm_test_check_mode_valid), 2458 KUNIT_CASE(drm_test_check_mode_valid_reject), 2459 KUNIT_CASE(drm_test_check_mode_valid_reject_rate), 2460 KUNIT_CASE(drm_test_check_mode_valid_reject_max_clock), 2461 { } 2462 }; 2463 2464 static struct kunit_suite drm_atomic_helper_connector_hdmi_mode_valid_test_suite = { 2465 .name = "drm_atomic_helper_connector_hdmi_mode_valid", 2466 .test_cases = drm_atomic_helper_connector_hdmi_mode_valid_tests, 2467 }; 2468 2469 kunit_test_suites( 2470 &drm_atomic_helper_connector_hdmi_check_test_suite, 2471 &drm_atomic_helper_connector_hdmi_reset_test_suite, 2472 &drm_atomic_helper_connector_hdmi_mode_valid_test_suite, 2473 ); 2474 2475 MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>"); 2476 MODULE_DESCRIPTION("Kunit test for drm_hdmi_state_helper functions"); 2477 MODULE_LICENSE("GPL"); 2478