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 int hdmi_update_failures; 40 }; 41 42 #define connector_to_priv(c) \ 43 container_of_const(c, struct drm_atomic_helper_connector_hdmi_priv, connector) 44 45 #define encoder_to_priv(e) \ 46 container_of_const(e, struct drm_atomic_helper_connector_hdmi_priv, encoder) 47 48 static struct drm_display_mode *find_preferred_mode(struct drm_connector *connector) 49 { 50 struct drm_device *drm = connector->dev; 51 struct drm_display_mode *mode, *preferred; 52 53 mutex_lock(&drm->mode_config.mutex); 54 preferred = list_first_entry_or_null(&connector->modes, struct drm_display_mode, head); 55 list_for_each_entry(mode, &connector->modes, head) 56 if (mode->type & DRM_MODE_TYPE_PREFERRED) 57 preferred = mode; 58 mutex_unlock(&drm->mode_config.mutex); 59 60 return preferred; 61 } 62 63 static int set_connector_edid(struct kunit *test, struct drm_connector *connector, 64 const void *edid, size_t edid_len) 65 { 66 struct drm_atomic_helper_connector_hdmi_priv *priv = 67 connector_to_priv(connector); 68 struct drm_device *drm = connector->dev; 69 int ret; 70 71 priv->current_edid = edid; 72 priv->current_edid_len = edid_len; 73 74 mutex_lock(&drm->mode_config.mutex); 75 ret = connector->funcs->fill_modes(connector, 4096, 4096); 76 mutex_unlock(&drm->mode_config.mutex); 77 78 return ret; 79 } 80 81 static int accept_infoframe_clear_infoframe(struct drm_connector *connector) 82 { 83 return 0; 84 } 85 86 static int accept_infoframe_write_infoframe(struct drm_connector *connector, 87 const u8 *buffer, size_t len) 88 { 89 return 0; 90 } 91 92 static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_funcs = { 93 .avi = { 94 .clear_infoframe = accept_infoframe_clear_infoframe, 95 .write_infoframe = accept_infoframe_write_infoframe, 96 }, 97 .hdmi = { 98 .clear_infoframe = accept_infoframe_clear_infoframe, 99 .write_infoframe = accept_infoframe_write_infoframe, 100 }, 101 }; 102 103 static enum drm_mode_status 104 reject_connector_tmds_char_rate_valid(const struct drm_connector *connector, 105 const struct drm_display_mode *mode, 106 unsigned long long tmds_rate) 107 { 108 return MODE_BAD; 109 } 110 111 static const struct drm_connector_hdmi_funcs reject_connector_hdmi_funcs = { 112 .tmds_char_rate_valid = reject_connector_tmds_char_rate_valid, 113 .avi = { 114 .clear_infoframe = accept_infoframe_clear_infoframe, 115 .write_infoframe = accept_infoframe_write_infoframe, 116 }, 117 .hdmi = { 118 .clear_infoframe = accept_infoframe_clear_infoframe, 119 .write_infoframe = accept_infoframe_write_infoframe, 120 }, 121 }; 122 123 static enum drm_mode_status 124 reject_100mhz_connector_tmds_char_rate_valid(const struct drm_connector *connector, 125 const struct drm_display_mode *mode, 126 unsigned long long tmds_rate) 127 { 128 return (tmds_rate > 100ULL * 1000 * 1000) ? MODE_BAD : MODE_OK; 129 } 130 131 static const struct drm_connector_hdmi_funcs reject_100mhz_connector_hdmi_funcs = { 132 .tmds_char_rate_valid = reject_100mhz_connector_tmds_char_rate_valid, 133 .avi = { 134 .clear_infoframe = accept_infoframe_clear_infoframe, 135 .write_infoframe = accept_infoframe_write_infoframe, 136 }, 137 .hdmi = { 138 .clear_infoframe = accept_infoframe_clear_infoframe, 139 .write_infoframe = accept_infoframe_write_infoframe, 140 }, 141 }; 142 143 static int dummy_connector_get_modes(struct drm_connector *connector) 144 { 145 struct drm_atomic_helper_connector_hdmi_priv *priv = 146 connector_to_priv(connector); 147 const struct drm_edid *edid; 148 unsigned int num_modes; 149 150 edid = drm_edid_alloc(priv->current_edid, priv->current_edid_len); 151 if (!edid) 152 return -EINVAL; 153 154 drm_edid_connector_update(connector, edid); 155 num_modes = drm_edid_connector_add_modes(connector); 156 157 drm_edid_free(edid); 158 159 return num_modes; 160 } 161 162 static const struct drm_connector_helper_funcs dummy_connector_helper_funcs = { 163 .atomic_check = drm_atomic_helper_connector_hdmi_check, 164 .get_modes = dummy_connector_get_modes, 165 .mode_valid = drm_hdmi_connector_mode_valid, 166 }; 167 168 static void dummy_hdmi_connector_reset(struct drm_connector *connector) 169 { 170 drm_atomic_helper_connector_reset(connector); 171 __drm_atomic_helper_connector_hdmi_reset(connector, connector->state); 172 } 173 174 static const struct drm_connector_funcs dummy_connector_funcs = { 175 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 176 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 177 .fill_modes = drm_helper_probe_single_connector_modes, 178 .reset = dummy_hdmi_connector_reset, 179 }; 180 181 static void test_encoder_atomic_enable(struct drm_encoder *encoder, 182 struct drm_atomic_state *state) 183 { 184 struct drm_atomic_helper_connector_hdmi_priv *priv = 185 encoder_to_priv(encoder); 186 int ret; 187 188 ret = drm_atomic_helper_connector_hdmi_update_infoframes(&priv->connector, state); 189 if (ret) 190 priv->hdmi_update_failures++; 191 } 192 193 static const struct drm_encoder_helper_funcs test_encoder_helper_funcs = { 194 .atomic_enable = test_encoder_atomic_enable, 195 }; 196 197 static 198 struct drm_atomic_helper_connector_hdmi_priv * 199 __connector_hdmi_init(struct kunit *test, 200 unsigned int formats, 201 unsigned int max_bpc, 202 const struct drm_connector_hdmi_funcs *hdmi_funcs, 203 const void *edid_data, size_t edid_len) 204 { 205 struct drm_atomic_helper_connector_hdmi_priv *priv; 206 struct drm_connector *conn; 207 struct drm_encoder *enc; 208 struct drm_device *drm; 209 struct device *dev; 210 int ret; 211 212 dev = drm_kunit_helper_alloc_device(test); 213 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); 214 215 priv = drm_kunit_helper_alloc_drm_device(test, dev, 216 struct drm_atomic_helper_connector_hdmi_priv, drm, 217 DRIVER_MODESET | DRIVER_ATOMIC); 218 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 219 test->priv = priv; 220 221 drm = &priv->drm; 222 priv->plane = drm_kunit_helper_create_primary_plane(test, drm, 223 NULL, 224 NULL, 225 NULL, 0, 226 NULL); 227 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->plane); 228 229 priv->crtc = drm_kunit_helper_create_crtc(test, drm, 230 priv->plane, NULL, 231 NULL, 232 NULL); 233 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->crtc); 234 235 enc = &priv->encoder; 236 ret = drmm_encoder_init(drm, enc, NULL, DRM_MODE_ENCODER_TMDS, NULL); 237 KUNIT_ASSERT_EQ(test, ret, 0); 238 239 enc->possible_crtcs = drm_crtc_mask(priv->crtc); 240 241 conn = &priv->connector; 242 conn->ycbcr_420_allowed = !!(formats & BIT(HDMI_COLORSPACE_YUV420)); 243 244 ret = drmm_connector_hdmi_init(drm, conn, 245 "Vendor", "Product", 246 &dummy_connector_funcs, 247 hdmi_funcs, 248 DRM_MODE_CONNECTOR_HDMIA, 249 NULL, 250 formats, 251 max_bpc); 252 KUNIT_ASSERT_EQ(test, ret, 0); 253 254 drm_connector_helper_add(conn, &dummy_connector_helper_funcs); 255 drm_connector_attach_encoder(conn, enc); 256 257 drm_mode_config_reset(drm); 258 259 if (edid_data && edid_len) { 260 ret = set_connector_edid(test, &priv->connector, edid_data, edid_len); 261 KUNIT_ASSERT_GT(test, ret, 0); 262 } 263 264 return priv; 265 } 266 267 #define drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, formats, max_bpc, funcs, edid) \ 268 __connector_hdmi_init(test, formats, max_bpc, funcs, edid, ARRAY_SIZE(edid)) 269 270 static 271 struct drm_atomic_helper_connector_hdmi_priv * 272 drm_kunit_helper_connector_hdmi_init(struct kunit *test, 273 unsigned int formats, 274 unsigned int max_bpc) 275 { 276 return drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 277 formats, 278 max_bpc, 279 &dummy_connector_hdmi_funcs, 280 test_edid_hdmi_1080p_rgb_max_200mhz); 281 } 282 283 /* 284 * Test that if we change the RGB quantization property to a different 285 * value, we trigger a mode change on the connector's CRTC, which will 286 * in turn disable/enable the connector. 287 */ 288 static void drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit *test) 289 { 290 struct drm_atomic_helper_connector_hdmi_priv *priv; 291 struct drm_modeset_acquire_ctx ctx; 292 struct drm_connector_state *old_conn_state; 293 struct drm_connector_state *new_conn_state; 294 struct drm_crtc_state *crtc_state; 295 struct drm_atomic_state *state; 296 struct drm_display_mode *preferred; 297 struct drm_connector *conn; 298 struct drm_device *drm; 299 struct drm_crtc *crtc; 300 int ret; 301 302 priv = drm_kunit_helper_connector_hdmi_init(test, 303 BIT(HDMI_COLORSPACE_RGB), 304 8); 305 KUNIT_ASSERT_NOT_NULL(test, priv); 306 307 drm = &priv->drm; 308 crtc = priv->crtc; 309 conn = &priv->connector; 310 311 preferred = find_preferred_mode(conn); 312 KUNIT_ASSERT_NOT_NULL(test, preferred); 313 314 drm_modeset_acquire_init(&ctx, 0); 315 316 retry_conn_enable: 317 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 318 crtc, conn, 319 preferred, 320 &ctx); 321 if (ret == -EDEADLK) { 322 ret = drm_modeset_backoff(&ctx); 323 if (!ret) 324 goto retry_conn_enable; 325 } 326 KUNIT_ASSERT_EQ(test, ret, 0); 327 328 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 329 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 330 331 new_conn_state = drm_atomic_get_connector_state(state, conn); 332 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 333 334 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 335 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 336 337 new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL; 338 339 KUNIT_ASSERT_NE(test, 340 old_conn_state->hdmi.broadcast_rgb, 341 new_conn_state->hdmi.broadcast_rgb); 342 343 ret = drm_atomic_check_only(state); 344 KUNIT_ASSERT_EQ(test, ret, 0); 345 346 new_conn_state = drm_atomic_get_new_connector_state(state, conn); 347 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 348 KUNIT_EXPECT_EQ(test, new_conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_FULL); 349 350 crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 351 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 352 KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed); 353 354 drm_modeset_drop_locks(&ctx); 355 drm_modeset_acquire_fini(&ctx); 356 } 357 358 /* 359 * Test that if we set the RGB quantization property to the same value, 360 * we don't trigger a mode change on the connector's CRTC and leave the 361 * connector unaffected. 362 */ 363 static void drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *test) 364 { 365 struct drm_atomic_helper_connector_hdmi_priv *priv; 366 struct drm_modeset_acquire_ctx ctx; 367 struct drm_connector_state *old_conn_state; 368 struct drm_connector_state *new_conn_state; 369 struct drm_crtc_state *crtc_state; 370 struct drm_atomic_state *state; 371 struct drm_display_mode *preferred; 372 struct drm_connector *conn; 373 struct drm_device *drm; 374 struct drm_crtc *crtc; 375 int ret; 376 377 priv = drm_kunit_helper_connector_hdmi_init(test, 378 BIT(HDMI_COLORSPACE_RGB), 379 8); 380 KUNIT_ASSERT_NOT_NULL(test, priv); 381 382 drm = &priv->drm; 383 crtc = priv->crtc; 384 conn = &priv->connector; 385 386 preferred = find_preferred_mode(conn); 387 KUNIT_ASSERT_NOT_NULL(test, preferred); 388 389 drm_modeset_acquire_init(&ctx, 0); 390 391 retry_conn_enable: 392 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 393 crtc, conn, 394 preferred, 395 &ctx); 396 if (ret == -EDEADLK) { 397 ret = drm_modeset_backoff(&ctx); 398 if (!ret) 399 goto retry_conn_enable; 400 } 401 KUNIT_ASSERT_EQ(test, ret, 0); 402 403 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 404 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 405 406 new_conn_state = drm_atomic_get_connector_state(state, conn); 407 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 408 409 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 410 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 411 412 new_conn_state->hdmi.broadcast_rgb = old_conn_state->hdmi.broadcast_rgb; 413 414 ret = drm_atomic_check_only(state); 415 KUNIT_ASSERT_EQ(test, ret, 0); 416 417 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 418 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 419 420 new_conn_state = drm_atomic_get_new_connector_state(state, conn); 421 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 422 423 KUNIT_EXPECT_EQ(test, 424 old_conn_state->hdmi.broadcast_rgb, 425 new_conn_state->hdmi.broadcast_rgb); 426 427 crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 428 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 429 KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed); 430 431 drm_modeset_drop_locks(&ctx); 432 drm_modeset_acquire_fini(&ctx); 433 } 434 435 /* 436 * Test that for an HDMI connector, with an HDMI monitor, if the 437 * Broadcast RGB property is set to auto with a mode that isn't the 438 * VIC-1 mode, we will get a limited RGB Quantization Range. 439 */ 440 static void drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit *test) 441 { 442 struct drm_atomic_helper_connector_hdmi_priv *priv; 443 struct drm_modeset_acquire_ctx ctx; 444 struct drm_connector_state *conn_state; 445 struct drm_atomic_state *state; 446 struct drm_display_mode *preferred; 447 struct drm_connector *conn; 448 struct drm_device *drm; 449 struct drm_crtc *crtc; 450 int ret; 451 452 priv = drm_kunit_helper_connector_hdmi_init(test, 453 BIT(HDMI_COLORSPACE_RGB), 454 8); 455 KUNIT_ASSERT_NOT_NULL(test, priv); 456 457 drm = &priv->drm; 458 crtc = priv->crtc; 459 conn = &priv->connector; 460 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 461 462 preferred = find_preferred_mode(conn); 463 KUNIT_ASSERT_NOT_NULL(test, preferred); 464 KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); 465 466 drm_modeset_acquire_init(&ctx, 0); 467 468 retry_conn_enable: 469 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 470 crtc, conn, 471 preferred, 472 &ctx); 473 if (ret == -EDEADLK) { 474 ret = drm_modeset_backoff(&ctx); 475 if (!ret) 476 goto retry_conn_enable; 477 } 478 KUNIT_ASSERT_EQ(test, ret, 0); 479 480 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 481 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 482 483 conn_state = drm_atomic_get_connector_state(state, conn); 484 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 485 486 KUNIT_ASSERT_EQ(test, 487 conn_state->hdmi.broadcast_rgb, 488 DRM_HDMI_BROADCAST_RGB_AUTO); 489 490 ret = drm_atomic_check_only(state); 491 KUNIT_ASSERT_EQ(test, ret, 0); 492 493 conn_state = drm_atomic_get_new_connector_state(state, conn); 494 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 495 496 KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); 497 498 drm_modeset_drop_locks(&ctx); 499 drm_modeset_acquire_fini(&ctx); 500 } 501 502 /* 503 * Test that for an HDMI connector, with an HDMI monitor, if the 504 * Broadcast RGB property is set to auto with a VIC-1 mode, we will get 505 * a full RGB Quantization Range. 506 */ 507 static void drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit *test) 508 { 509 struct drm_atomic_helper_connector_hdmi_priv *priv; 510 struct drm_modeset_acquire_ctx ctx; 511 struct drm_connector_state *conn_state; 512 struct drm_atomic_state *state; 513 struct drm_display_mode *mode; 514 struct drm_connector *conn; 515 struct drm_device *drm; 516 struct drm_crtc *crtc; 517 int ret; 518 519 priv = drm_kunit_helper_connector_hdmi_init(test, 520 BIT(HDMI_COLORSPACE_RGB), 521 8); 522 KUNIT_ASSERT_NOT_NULL(test, priv); 523 524 drm = &priv->drm; 525 conn = &priv->connector; 526 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 527 528 drm_modeset_acquire_init(&ctx, 0); 529 530 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); 531 KUNIT_ASSERT_NOT_NULL(test, mode); 532 533 crtc = priv->crtc; 534 535 retry_conn_enable: 536 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 537 crtc, conn, 538 mode, 539 &ctx); 540 if (ret == -EDEADLK) { 541 ret = drm_modeset_backoff(&ctx); 542 if (!ret) 543 goto retry_conn_enable; 544 } 545 KUNIT_ASSERT_EQ(test, ret, 0); 546 547 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 548 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 549 550 conn_state = drm_atomic_get_connector_state(state, conn); 551 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 552 553 KUNIT_ASSERT_EQ(test, 554 conn_state->hdmi.broadcast_rgb, 555 DRM_HDMI_BROADCAST_RGB_AUTO); 556 557 ret = drm_atomic_check_only(state); 558 KUNIT_ASSERT_EQ(test, ret, 0); 559 560 conn_state = drm_atomic_get_new_connector_state(state, conn); 561 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 562 563 KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range); 564 565 drm_modeset_drop_locks(&ctx); 566 drm_modeset_acquire_fini(&ctx); 567 } 568 569 /* 570 * Test that for an HDMI connector, with an HDMI monitor, if the 571 * Broadcast RGB property is set to full with a mode that isn't the 572 * VIC-1 mode, we will get a full RGB Quantization Range. 573 */ 574 static void drm_test_check_broadcast_rgb_full_cea_mode(struct kunit *test) 575 { 576 struct drm_atomic_helper_connector_hdmi_priv *priv; 577 struct drm_modeset_acquire_ctx ctx; 578 struct drm_connector_state *conn_state; 579 struct drm_atomic_state *state; 580 struct drm_display_mode *preferred; 581 struct drm_connector *conn; 582 struct drm_device *drm; 583 struct drm_crtc *crtc; 584 int ret; 585 586 priv = drm_kunit_helper_connector_hdmi_init(test, 587 BIT(HDMI_COLORSPACE_RGB), 588 8); 589 KUNIT_ASSERT_NOT_NULL(test, priv); 590 591 drm = &priv->drm; 592 crtc = priv->crtc; 593 conn = &priv->connector; 594 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 595 596 preferred = find_preferred_mode(conn); 597 KUNIT_ASSERT_NOT_NULL(test, preferred); 598 KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); 599 600 drm_modeset_acquire_init(&ctx, 0); 601 602 retry_conn_enable: 603 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 604 crtc, conn, 605 preferred, 606 &ctx); 607 if (ret == -EDEADLK) { 608 ret = drm_modeset_backoff(&ctx); 609 if (!ret) 610 goto retry_conn_enable; 611 } 612 KUNIT_ASSERT_EQ(test, ret, 0); 613 614 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 615 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 616 617 conn_state = drm_atomic_get_connector_state(state, conn); 618 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 619 620 conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL; 621 622 ret = drm_atomic_check_only(state); 623 KUNIT_ASSERT_EQ(test, ret, 0); 624 625 conn_state = drm_atomic_get_new_connector_state(state, conn); 626 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 627 628 KUNIT_ASSERT_EQ(test, 629 conn_state->hdmi.broadcast_rgb, 630 DRM_HDMI_BROADCAST_RGB_FULL); 631 632 KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range); 633 634 drm_modeset_drop_locks(&ctx); 635 drm_modeset_acquire_fini(&ctx); 636 } 637 638 /* 639 * Test that for an HDMI connector, with an HDMI monitor, if the 640 * Broadcast RGB property is set to full with a VIC-1 mode, we will get 641 * a full RGB Quantization Range. 642 */ 643 static void drm_test_check_broadcast_rgb_full_cea_mode_vic_1(struct kunit *test) 644 { 645 struct drm_atomic_helper_connector_hdmi_priv *priv; 646 struct drm_modeset_acquire_ctx ctx; 647 struct drm_connector_state *conn_state; 648 struct drm_atomic_state *state; 649 struct drm_display_mode *mode; 650 struct drm_connector *conn; 651 struct drm_device *drm; 652 struct drm_crtc *crtc; 653 int ret; 654 655 priv = drm_kunit_helper_connector_hdmi_init(test, 656 BIT(HDMI_COLORSPACE_RGB), 657 8); 658 KUNIT_ASSERT_NOT_NULL(test, priv); 659 660 drm = &priv->drm; 661 conn = &priv->connector; 662 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 663 664 drm_modeset_acquire_init(&ctx, 0); 665 666 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); 667 KUNIT_ASSERT_NOT_NULL(test, mode); 668 669 crtc = priv->crtc; 670 671 retry_conn_enable: 672 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 673 crtc, conn, 674 mode, 675 &ctx); 676 if (ret == -EDEADLK) { 677 ret = drm_modeset_backoff(&ctx); 678 if (!ret) 679 goto retry_conn_enable; 680 } 681 KUNIT_ASSERT_EQ(test, ret, 0); 682 683 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 684 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 685 686 conn_state = drm_atomic_get_connector_state(state, conn); 687 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 688 689 conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL; 690 691 ret = drm_atomic_check_only(state); 692 KUNIT_ASSERT_EQ(test, ret, 0); 693 694 conn_state = drm_atomic_get_new_connector_state(state, conn); 695 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 696 697 KUNIT_ASSERT_EQ(test, 698 conn_state->hdmi.broadcast_rgb, 699 DRM_HDMI_BROADCAST_RGB_FULL); 700 701 KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range); 702 703 drm_modeset_drop_locks(&ctx); 704 drm_modeset_acquire_fini(&ctx); 705 } 706 707 /* 708 * Test that for an HDMI connector, with an HDMI monitor, if the 709 * Broadcast RGB property is set to limited with a mode that isn't the 710 * VIC-1 mode, we will get a limited RGB Quantization Range. 711 */ 712 static void drm_test_check_broadcast_rgb_limited_cea_mode(struct kunit *test) 713 { 714 struct drm_atomic_helper_connector_hdmi_priv *priv; 715 struct drm_modeset_acquire_ctx ctx; 716 struct drm_connector_state *conn_state; 717 struct drm_atomic_state *state; 718 struct drm_display_mode *preferred; 719 struct drm_connector *conn; 720 struct drm_device *drm; 721 struct drm_crtc *crtc; 722 int ret; 723 724 priv = drm_kunit_helper_connector_hdmi_init(test, 725 BIT(HDMI_COLORSPACE_RGB), 726 8); 727 KUNIT_ASSERT_NOT_NULL(test, priv); 728 729 drm = &priv->drm; 730 crtc = priv->crtc; 731 conn = &priv->connector; 732 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 733 734 preferred = find_preferred_mode(conn); 735 KUNIT_ASSERT_NOT_NULL(test, preferred); 736 KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1); 737 738 drm_modeset_acquire_init(&ctx, 0); 739 740 retry_conn_enable: 741 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 742 crtc, conn, 743 preferred, 744 &ctx); 745 if (ret == -EDEADLK) { 746 ret = drm_modeset_backoff(&ctx); 747 if (!ret) 748 goto retry_conn_enable; 749 } 750 KUNIT_ASSERT_EQ(test, ret, 0); 751 752 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 753 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 754 755 conn_state = drm_atomic_get_connector_state(state, conn); 756 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 757 758 conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED; 759 760 ret = drm_atomic_check_only(state); 761 KUNIT_ASSERT_EQ(test, ret, 0); 762 763 conn_state = drm_atomic_get_new_connector_state(state, conn); 764 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 765 766 KUNIT_ASSERT_EQ(test, 767 conn_state->hdmi.broadcast_rgb, 768 DRM_HDMI_BROADCAST_RGB_LIMITED); 769 770 KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); 771 772 drm_modeset_drop_locks(&ctx); 773 drm_modeset_acquire_fini(&ctx); 774 } 775 776 /* 777 * Test that for an HDMI connector, with an HDMI monitor, if the 778 * Broadcast RGB property is set to limited with a VIC-1 mode, we will 779 * get a limited RGB Quantization Range. 780 */ 781 static void drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit *test) 782 { 783 struct drm_atomic_helper_connector_hdmi_priv *priv; 784 struct drm_modeset_acquire_ctx ctx; 785 struct drm_connector_state *conn_state; 786 struct drm_atomic_state *state; 787 struct drm_display_mode *mode; 788 struct drm_connector *conn; 789 struct drm_device *drm; 790 struct drm_crtc *crtc; 791 int ret; 792 793 priv = drm_kunit_helper_connector_hdmi_init(test, 794 BIT(HDMI_COLORSPACE_RGB), 795 8); 796 KUNIT_ASSERT_NOT_NULL(test, priv); 797 798 drm = &priv->drm; 799 conn = &priv->connector; 800 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 801 802 drm_modeset_acquire_init(&ctx, 0); 803 804 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); 805 KUNIT_ASSERT_NOT_NULL(test, mode); 806 807 crtc = priv->crtc; 808 809 retry_conn_enable: 810 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 811 crtc, conn, 812 mode, 813 &ctx); 814 if (ret == -EDEADLK) { 815 ret = drm_modeset_backoff(&ctx); 816 if (!ret) 817 goto retry_conn_enable; 818 } 819 KUNIT_ASSERT_EQ(test, ret, 0); 820 821 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 822 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 823 824 conn_state = drm_atomic_get_connector_state(state, conn); 825 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 826 827 conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED; 828 829 ret = drm_atomic_check_only(state); 830 KUNIT_ASSERT_EQ(test, ret, 0); 831 832 conn_state = drm_atomic_get_new_connector_state(state, conn); 833 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 834 835 KUNIT_ASSERT_EQ(test, 836 conn_state->hdmi.broadcast_rgb, 837 DRM_HDMI_BROADCAST_RGB_LIMITED); 838 839 KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); 840 841 drm_modeset_drop_locks(&ctx); 842 drm_modeset_acquire_fini(&ctx); 843 } 844 845 /* 846 * Test that for an HDMI connector, with an HDMI monitor, we will 847 * get a limited RGB Quantization Range with a YUV420 mode, no 848 * matter what the value of the Broadcast RGB property is set to. 849 */ 850 static void drm_test_check_broadcast_rgb_cea_mode_yuv420(struct kunit *test) 851 { 852 struct drm_atomic_helper_connector_hdmi_priv *priv; 853 enum drm_hdmi_broadcast_rgb broadcast_rgb; 854 struct drm_modeset_acquire_ctx ctx; 855 struct drm_connector_state *conn_state; 856 struct drm_atomic_state *state; 857 struct drm_display_mode *mode; 858 struct drm_connector *conn; 859 struct drm_device *drm; 860 struct drm_crtc *crtc; 861 int ret; 862 863 broadcast_rgb = *(enum drm_hdmi_broadcast_rgb *)test->param_value; 864 865 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 866 BIT(HDMI_COLORSPACE_RGB) | 867 BIT(HDMI_COLORSPACE_YUV420), 868 8, 869 &dummy_connector_hdmi_funcs, 870 test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); 871 KUNIT_ASSERT_NOT_NULL(test, priv); 872 873 drm = &priv->drm; 874 crtc = priv->crtc; 875 conn = &priv->connector; 876 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi); 877 878 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95); 879 KUNIT_ASSERT_NOT_NULL(test, mode); 880 881 drm_modeset_acquire_init(&ctx, 0); 882 883 retry_conn_enable: 884 ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, 885 mode, &ctx); 886 if (ret == -EDEADLK) { 887 ret = drm_modeset_backoff(&ctx); 888 if (!ret) 889 goto retry_conn_enable; 890 } 891 KUNIT_ASSERT_EQ(test, ret, 0); 892 893 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 894 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 895 896 retry_conn_state: 897 conn_state = drm_atomic_get_connector_state(state, conn); 898 if (PTR_ERR(conn_state) == -EDEADLK) { 899 drm_atomic_state_clear(state); 900 ret = drm_modeset_backoff(&ctx); 901 if (!ret) 902 goto retry_conn_state; 903 } 904 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 905 906 conn_state->hdmi.broadcast_rgb = broadcast_rgb; 907 908 ret = drm_atomic_check_only(state); 909 if (ret == -EDEADLK) { 910 drm_atomic_state_clear(state); 911 ret = drm_modeset_backoff(&ctx); 912 if (!ret) 913 goto retry_conn_state; 914 } 915 KUNIT_ASSERT_EQ(test, ret, 0); 916 917 conn_state = drm_atomic_get_new_connector_state(state, conn); 918 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 919 920 KUNIT_ASSERT_EQ(test, conn_state->hdmi.broadcast_rgb, broadcast_rgb); 921 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420); 922 923 KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range); 924 925 drm_modeset_drop_locks(&ctx); 926 drm_modeset_acquire_fini(&ctx); 927 } 928 929 static const enum drm_hdmi_broadcast_rgb check_broadcast_rgb_cea_mode_yuv420_tests[] = { 930 DRM_HDMI_BROADCAST_RGB_AUTO, 931 DRM_HDMI_BROADCAST_RGB_FULL, 932 DRM_HDMI_BROADCAST_RGB_LIMITED, 933 }; 934 935 static void 936 check_broadcast_rgb_cea_mode_yuv420_desc(const enum drm_hdmi_broadcast_rgb *broadcast_rgb, 937 char *desc) 938 { 939 sprintf(desc, "%s", drm_hdmi_connector_get_broadcast_rgb_name(*broadcast_rgb)); 940 } 941 942 KUNIT_ARRAY_PARAM(check_broadcast_rgb_cea_mode_yuv420, 943 check_broadcast_rgb_cea_mode_yuv420_tests, 944 check_broadcast_rgb_cea_mode_yuv420_desc); 945 946 /* 947 * Test that if we change the maximum bpc property to a different value, 948 * we trigger a mode change on the connector's CRTC, which will in turn 949 * disable/enable the connector. 950 */ 951 static void drm_test_check_output_bpc_crtc_mode_changed(struct kunit *test) 952 { 953 struct drm_atomic_helper_connector_hdmi_priv *priv; 954 struct drm_modeset_acquire_ctx ctx; 955 struct drm_connector_state *old_conn_state; 956 struct drm_connector_state *new_conn_state; 957 struct drm_crtc_state *crtc_state; 958 struct drm_atomic_state *state; 959 struct drm_display_mode *preferred; 960 struct drm_connector *conn; 961 struct drm_device *drm; 962 struct drm_crtc *crtc; 963 int ret; 964 965 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 966 BIT(HDMI_COLORSPACE_RGB), 967 10, 968 &dummy_connector_hdmi_funcs, 969 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); 970 KUNIT_ASSERT_NOT_NULL(test, priv); 971 972 drm = &priv->drm; 973 crtc = priv->crtc; 974 conn = &priv->connector; 975 preferred = find_preferred_mode(conn); 976 KUNIT_ASSERT_NOT_NULL(test, preferred); 977 978 drm_modeset_acquire_init(&ctx, 0); 979 980 retry_conn_enable: 981 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 982 crtc, conn, 983 preferred, 984 &ctx); 985 if (ret == -EDEADLK) { 986 ret = drm_modeset_backoff(&ctx); 987 if (!ret) 988 goto retry_conn_enable; 989 } 990 KUNIT_ASSERT_EQ(test, ret, 0); 991 992 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 993 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 994 995 new_conn_state = drm_atomic_get_connector_state(state, conn); 996 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 997 998 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 999 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 1000 1001 new_conn_state->max_requested_bpc = 8; 1002 1003 KUNIT_ASSERT_NE(test, 1004 old_conn_state->max_requested_bpc, 1005 new_conn_state->max_requested_bpc); 1006 1007 ret = drm_atomic_check_only(state); 1008 KUNIT_ASSERT_EQ(test, ret, 0); 1009 1010 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 1011 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 1012 1013 new_conn_state = drm_atomic_get_new_connector_state(state, conn); 1014 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 1015 1016 KUNIT_ASSERT_NE(test, 1017 old_conn_state->hdmi.output_bpc, 1018 new_conn_state->hdmi.output_bpc); 1019 1020 crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 1021 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 1022 KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed); 1023 1024 drm_modeset_drop_locks(&ctx); 1025 drm_modeset_acquire_fini(&ctx); 1026 } 1027 1028 /* 1029 * Test that if we set the output bpc property to the same value, we 1030 * don't trigger a mode change on the connector's CRTC and leave the 1031 * connector unaffected. 1032 */ 1033 static void drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test) 1034 { 1035 struct drm_atomic_helper_connector_hdmi_priv *priv; 1036 struct drm_modeset_acquire_ctx ctx; 1037 struct drm_connector_state *old_conn_state; 1038 struct drm_connector_state *new_conn_state; 1039 struct drm_crtc_state *crtc_state; 1040 struct drm_atomic_state *state; 1041 struct drm_display_mode *preferred; 1042 struct drm_connector *conn; 1043 struct drm_device *drm; 1044 struct drm_crtc *crtc; 1045 int ret; 1046 1047 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1048 BIT(HDMI_COLORSPACE_RGB), 1049 10, 1050 &dummy_connector_hdmi_funcs, 1051 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); 1052 KUNIT_ASSERT_NOT_NULL(test, priv); 1053 1054 drm = &priv->drm; 1055 crtc = priv->crtc; 1056 conn = &priv->connector; 1057 preferred = find_preferred_mode(conn); 1058 KUNIT_ASSERT_NOT_NULL(test, preferred); 1059 1060 drm_modeset_acquire_init(&ctx, 0); 1061 1062 retry_conn_enable: 1063 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1064 crtc, conn, 1065 preferred, 1066 &ctx); 1067 if (ret == -EDEADLK) { 1068 ret = drm_modeset_backoff(&ctx); 1069 if (!ret) 1070 goto retry_conn_enable; 1071 } 1072 KUNIT_ASSERT_EQ(test, ret, 0); 1073 1074 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 1075 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 1076 1077 new_conn_state = drm_atomic_get_connector_state(state, conn); 1078 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 1079 1080 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 1081 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 1082 1083 KUNIT_ASSERT_EQ(test, 1084 new_conn_state->hdmi.output_bpc, 1085 old_conn_state->hdmi.output_bpc); 1086 1087 ret = drm_atomic_check_only(state); 1088 KUNIT_ASSERT_EQ(test, ret, 0); 1089 1090 old_conn_state = drm_atomic_get_old_connector_state(state, conn); 1091 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state); 1092 1093 new_conn_state = drm_atomic_get_new_connector_state(state, conn); 1094 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 1095 1096 KUNIT_EXPECT_EQ(test, 1097 old_conn_state->hdmi.output_bpc, 1098 new_conn_state->hdmi.output_bpc); 1099 1100 crtc_state = drm_atomic_get_new_crtc_state(state, crtc); 1101 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 1102 KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed); 1103 1104 drm_modeset_drop_locks(&ctx); 1105 drm_modeset_acquire_fini(&ctx); 1106 } 1107 1108 /* 1109 * Test that if we have an HDMI connector but a !HDMI display, we always 1110 * output RGB with 8 bpc. 1111 */ 1112 static void drm_test_check_output_bpc_dvi(struct kunit *test) 1113 { 1114 struct drm_atomic_helper_connector_hdmi_priv *priv; 1115 struct drm_modeset_acquire_ctx ctx; 1116 struct drm_connector_state *conn_state; 1117 struct drm_display_info *info; 1118 struct drm_display_mode *preferred; 1119 struct drm_connector *conn; 1120 struct drm_device *drm; 1121 struct drm_crtc *crtc; 1122 int ret; 1123 1124 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1125 BIT(HDMI_COLORSPACE_RGB) | 1126 BIT(HDMI_COLORSPACE_YUV422) | 1127 BIT(HDMI_COLORSPACE_YUV444), 1128 12, 1129 &dummy_connector_hdmi_funcs, 1130 test_edid_dvi_1080p); 1131 KUNIT_ASSERT_NOT_NULL(test, priv); 1132 1133 drm = &priv->drm; 1134 crtc = priv->crtc; 1135 conn = &priv->connector; 1136 info = &conn->display_info; 1137 KUNIT_ASSERT_FALSE(test, info->is_hdmi); 1138 1139 preferred = find_preferred_mode(conn); 1140 KUNIT_ASSERT_NOT_NULL(test, preferred); 1141 1142 drm_modeset_acquire_init(&ctx, 0); 1143 1144 retry_conn_enable: 1145 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1146 crtc, conn, 1147 preferred, 1148 &ctx); 1149 if (ret == -EDEADLK) { 1150 ret = drm_modeset_backoff(&ctx); 1151 if (!ret) 1152 goto retry_conn_enable; 1153 } 1154 KUNIT_ASSERT_EQ(test, ret, 0); 1155 1156 conn_state = conn->state; 1157 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1158 1159 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 1160 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1161 1162 drm_modeset_drop_locks(&ctx); 1163 drm_modeset_acquire_fini(&ctx); 1164 } 1165 1166 /* 1167 * Test that when doing a commit which would use RGB 8bpc, the TMDS 1168 * clock rate stored in the connector state is equal to the mode clock 1169 */ 1170 static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test) 1171 { 1172 struct drm_atomic_helper_connector_hdmi_priv *priv; 1173 struct drm_modeset_acquire_ctx ctx; 1174 struct drm_connector_state *conn_state; 1175 struct drm_display_mode *preferred; 1176 struct drm_connector *conn; 1177 struct drm_device *drm; 1178 struct drm_crtc *crtc; 1179 int ret; 1180 1181 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1182 BIT(HDMI_COLORSPACE_RGB), 1183 8, 1184 &dummy_connector_hdmi_funcs, 1185 test_edid_hdmi_1080p_rgb_max_200mhz); 1186 KUNIT_ASSERT_NOT_NULL(test, priv); 1187 1188 drm = &priv->drm; 1189 crtc = priv->crtc; 1190 conn = &priv->connector; 1191 preferred = find_preferred_mode(conn); 1192 KUNIT_ASSERT_NOT_NULL(test, preferred); 1193 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1194 1195 drm_modeset_acquire_init(&ctx, 0); 1196 1197 retry_conn_enable: 1198 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1199 crtc, conn, 1200 preferred, 1201 &ctx); 1202 if (ret == -EDEADLK) { 1203 ret = drm_modeset_backoff(&ctx); 1204 if (!ret) 1205 goto retry_conn_enable; 1206 } 1207 KUNIT_ASSERT_EQ(test, ret, 0); 1208 1209 conn_state = conn->state; 1210 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1211 1212 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 8); 1213 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1214 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1000); 1215 1216 drm_modeset_drop_locks(&ctx); 1217 drm_modeset_acquire_fini(&ctx); 1218 } 1219 1220 /* 1221 * Test that when doing a commit which would use RGB 10bpc, the TMDS 1222 * clock rate stored in the connector state is equal to 1.25 times the 1223 * mode pixel clock 1224 */ 1225 static void drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit *test) 1226 { 1227 struct drm_atomic_helper_connector_hdmi_priv *priv; 1228 struct drm_modeset_acquire_ctx ctx; 1229 struct drm_connector_state *conn_state; 1230 struct drm_display_mode *preferred; 1231 struct drm_connector *conn; 1232 struct drm_device *drm; 1233 struct drm_crtc *crtc; 1234 int ret; 1235 1236 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1237 BIT(HDMI_COLORSPACE_RGB), 1238 10, 1239 &dummy_connector_hdmi_funcs, 1240 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz); 1241 KUNIT_ASSERT_NOT_NULL(test, priv); 1242 1243 drm = &priv->drm; 1244 crtc = priv->crtc; 1245 conn = &priv->connector; 1246 preferred = find_preferred_mode(conn); 1247 KUNIT_ASSERT_NOT_NULL(test, preferred); 1248 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1249 1250 drm_modeset_acquire_init(&ctx, 0); 1251 1252 retry_conn_enable: 1253 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1254 crtc, conn, 1255 preferred, 1256 &ctx); 1257 if (ret == -EDEADLK) { 1258 ret = drm_modeset_backoff(&ctx); 1259 if (!ret) 1260 goto retry_conn_enable; 1261 } 1262 KUNIT_ASSERT_EQ(test, ret, 0); 1263 1264 conn_state = conn->state; 1265 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1266 1267 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 10); 1268 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1269 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250); 1270 1271 drm_modeset_drop_locks(&ctx); 1272 drm_modeset_acquire_fini(&ctx); 1273 } 1274 1275 /* 1276 * Test that when doing a commit which would use RGB 12bpc, the TMDS 1277 * clock rate stored in the connector state is equal to 1.5 times the 1278 * mode pixel clock 1279 */ 1280 static void drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test) 1281 { 1282 struct drm_atomic_helper_connector_hdmi_priv *priv; 1283 struct drm_modeset_acquire_ctx ctx; 1284 struct drm_connector_state *conn_state; 1285 struct drm_display_mode *preferred; 1286 struct drm_connector *conn; 1287 struct drm_device *drm; 1288 struct drm_crtc *crtc; 1289 int ret; 1290 1291 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1292 BIT(HDMI_COLORSPACE_RGB), 1293 12, 1294 &dummy_connector_hdmi_funcs, 1295 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz); 1296 KUNIT_ASSERT_NOT_NULL(test, priv); 1297 1298 drm = &priv->drm; 1299 crtc = priv->crtc; 1300 conn = &priv->connector; 1301 preferred = find_preferred_mode(conn); 1302 KUNIT_ASSERT_NOT_NULL(test, preferred); 1303 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1304 1305 drm_modeset_acquire_init(&ctx, 0); 1306 1307 retry_conn_enable: 1308 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1309 crtc, conn, 1310 preferred, 1311 &ctx); 1312 if (ret == -EDEADLK) { 1313 ret = drm_modeset_backoff(&ctx); 1314 if (!ret) 1315 goto retry_conn_enable; 1316 } 1317 KUNIT_ASSERT_EQ(test, ret, 0); 1318 1319 conn_state = conn->state; 1320 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1321 1322 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 12); 1323 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1324 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1500); 1325 1326 drm_modeset_drop_locks(&ctx); 1327 drm_modeset_acquire_fini(&ctx); 1328 } 1329 1330 /* 1331 * Test that if we filter a rate through our hook, it's indeed rejected 1332 * by the whole atomic_check logic. 1333 * 1334 * We do so by first doing a commit on the pipeline to make sure that it 1335 * works, change the HDMI helpers pointer, and then try the same commit 1336 * again to see if it fails as it should. 1337 */ 1338 static void drm_test_check_hdmi_funcs_reject_rate(struct kunit *test) 1339 { 1340 struct drm_atomic_helper_connector_hdmi_priv *priv; 1341 struct drm_modeset_acquire_ctx ctx; 1342 struct drm_atomic_state *state; 1343 struct drm_display_mode *preferred; 1344 struct drm_crtc_state *crtc_state; 1345 struct drm_connector *conn; 1346 struct drm_device *drm; 1347 struct drm_crtc *crtc; 1348 int ret; 1349 1350 priv = drm_kunit_helper_connector_hdmi_init(test, 1351 BIT(HDMI_COLORSPACE_RGB), 1352 8); 1353 KUNIT_ASSERT_NOT_NULL(test, priv); 1354 1355 drm = &priv->drm; 1356 crtc = priv->crtc; 1357 conn = &priv->connector; 1358 1359 preferred = find_preferred_mode(conn); 1360 KUNIT_ASSERT_NOT_NULL(test, preferred); 1361 1362 drm_modeset_acquire_init(&ctx, 0); 1363 1364 retry_conn_enable: 1365 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1366 crtc, conn, 1367 preferred, 1368 &ctx); 1369 if (ret == -EDEADLK) { 1370 ret = drm_modeset_backoff(&ctx); 1371 if (!ret) 1372 goto retry_conn_enable; 1373 } 1374 KUNIT_ASSERT_EQ(test, ret, 0); 1375 1376 /* You shouldn't be doing that at home. */ 1377 conn->hdmi.funcs = &reject_connector_hdmi_funcs; 1378 1379 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 1380 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 1381 1382 crtc_state = drm_atomic_get_crtc_state(state, crtc); 1383 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 1384 1385 crtc_state->connectors_changed = true; 1386 1387 ret = drm_atomic_check_only(state); 1388 KUNIT_EXPECT_LT(test, ret, 0); 1389 1390 drm_modeset_drop_locks(&ctx); 1391 drm_modeset_acquire_fini(&ctx); 1392 } 1393 1394 /* 1395 * Test that if: 1396 * - We have an HDMI connector supporting RGB only 1397 * - The chosen mode has a TMDS character rate higher than the display 1398 * supports in RGB/12bpc 1399 * - The chosen mode has a TMDS character rate lower than the display 1400 * supports in RGB/10bpc. 1401 * 1402 * Then we will pick the latter, and the computed TMDS character rate 1403 * will be equal to 1.25 times the mode pixel clock. 1404 */ 1405 static void drm_test_check_max_tmds_rate_bpc_fallback_rgb(struct kunit *test) 1406 { 1407 struct drm_atomic_helper_connector_hdmi_priv *priv; 1408 struct drm_modeset_acquire_ctx ctx; 1409 struct drm_connector_state *conn_state; 1410 struct drm_display_info *info; 1411 struct drm_display_mode *preferred; 1412 unsigned long long rate; 1413 struct drm_connector *conn; 1414 struct drm_device *drm; 1415 struct drm_crtc *crtc; 1416 int ret; 1417 1418 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1419 BIT(HDMI_COLORSPACE_RGB), 1420 12, 1421 &dummy_connector_hdmi_funcs, 1422 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); 1423 KUNIT_ASSERT_NOT_NULL(test, priv); 1424 1425 drm = &priv->drm; 1426 crtc = priv->crtc; 1427 conn = &priv->connector; 1428 info = &conn->display_info; 1429 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1430 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1431 1432 preferred = find_preferred_mode(conn); 1433 KUNIT_ASSERT_NOT_NULL(test, preferred); 1434 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1435 1436 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1437 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1438 1439 rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); 1440 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1441 1442 drm_modeset_acquire_init(&ctx, 0); 1443 1444 retry_conn_enable: 1445 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1446 crtc, conn, 1447 preferred, 1448 &ctx); 1449 if (ret == -EDEADLK) { 1450 ret = drm_modeset_backoff(&ctx); 1451 if (!ret) 1452 goto retry_conn_enable; 1453 } 1454 KUNIT_EXPECT_EQ(test, ret, 0); 1455 1456 conn_state = conn->state; 1457 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1458 1459 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); 1460 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1461 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250); 1462 1463 drm_modeset_drop_locks(&ctx); 1464 drm_modeset_acquire_fini(&ctx); 1465 } 1466 1467 /* 1468 * Test that if: 1469 * - We have an HDMI connector and a display supporting both RGB and YUV420 1470 * - The chosen mode can be supported in YUV420 output format only 1471 * - The chosen mode has a TMDS character rate higher than the display 1472 * supports in YUV420/12bpc 1473 * - The chosen mode has a TMDS character rate lower than the display 1474 * supports in YUV420/10bpc. 1475 * 1476 * Then we will pick the latter, and the computed TMDS character rate 1477 * will be equal to 1.25 * 0.5 times the mode pixel clock. 1478 */ 1479 static void drm_test_check_max_tmds_rate_bpc_fallback_yuv420(struct kunit *test) 1480 { 1481 struct drm_atomic_helper_connector_hdmi_priv *priv; 1482 struct drm_modeset_acquire_ctx ctx; 1483 struct drm_connector_state *conn_state; 1484 struct drm_display_info *info; 1485 struct drm_display_mode *yuv420_only_mode; 1486 unsigned long long rate; 1487 struct drm_connector *conn; 1488 struct drm_device *drm; 1489 struct drm_crtc *crtc; 1490 int ret; 1491 1492 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1493 BIT(HDMI_COLORSPACE_RGB) | 1494 BIT(HDMI_COLORSPACE_YUV420), 1495 12, 1496 &dummy_connector_hdmi_funcs, 1497 test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); 1498 KUNIT_ASSERT_NOT_NULL(test, priv); 1499 1500 drm = &priv->drm; 1501 crtc = priv->crtc; 1502 conn = &priv->connector; 1503 info = &conn->display_info; 1504 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1505 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1506 KUNIT_ASSERT_TRUE(test, conn->ycbcr_420_allowed); 1507 1508 yuv420_only_mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95); 1509 KUNIT_ASSERT_NOT_NULL(test, yuv420_only_mode); 1510 KUNIT_ASSERT_TRUE(test, drm_mode_is_420_only(info, yuv420_only_mode)); 1511 1512 rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 12, HDMI_COLORSPACE_YUV420); 1513 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1514 1515 rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 10, HDMI_COLORSPACE_YUV420); 1516 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1517 1518 drm_modeset_acquire_init(&ctx, 0); 1519 1520 retry_conn_enable: 1521 ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, 1522 yuv420_only_mode, &ctx); 1523 if (ret == -EDEADLK) { 1524 ret = drm_modeset_backoff(&ctx); 1525 if (!ret) 1526 goto retry_conn_enable; 1527 } 1528 KUNIT_EXPECT_EQ(test, ret, 0); 1529 1530 conn_state = conn->state; 1531 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1532 1533 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); 1534 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420); 1535 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, yuv420_only_mode->clock * 625); 1536 1537 drm_modeset_drop_locks(&ctx); 1538 drm_modeset_acquire_fini(&ctx); 1539 } 1540 1541 /* 1542 * Test that if: 1543 * - We have an HDMI connector supporting both RGB and YUV422 and up to 1544 * 12 bpc 1545 * - The chosen mode has a TMDS character rate higher than the display 1546 * supports in RGB/12bpc but lower than the display supports in 1547 * RGB/10bpc 1548 * - The chosen mode has a TMDS character rate lower than the display 1549 * supports in YUV422/12bpc. 1550 * 1551 * Then we will prefer to keep the RGB format with a lower bpc over 1552 * picking YUV422. 1553 */ 1554 static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422(struct kunit *test) 1555 { 1556 struct drm_atomic_helper_connector_hdmi_priv *priv; 1557 struct drm_modeset_acquire_ctx ctx; 1558 struct drm_connector_state *conn_state; 1559 struct drm_display_info *info; 1560 struct drm_display_mode *preferred; 1561 unsigned long long rate; 1562 struct drm_connector *conn; 1563 struct drm_device *drm; 1564 struct drm_crtc *crtc; 1565 int ret; 1566 1567 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1568 BIT(HDMI_COLORSPACE_RGB) | 1569 BIT(HDMI_COLORSPACE_YUV422) | 1570 BIT(HDMI_COLORSPACE_YUV444), 1571 12, 1572 &dummy_connector_hdmi_funcs, 1573 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); 1574 KUNIT_ASSERT_NOT_NULL(test, priv); 1575 1576 drm = &priv->drm; 1577 crtc = priv->crtc; 1578 conn = &priv->connector; 1579 info = &conn->display_info; 1580 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1581 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1582 1583 preferred = find_preferred_mode(conn); 1584 KUNIT_ASSERT_NOT_NULL(test, preferred); 1585 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1586 1587 rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); 1588 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1589 1590 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1591 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1592 1593 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); 1594 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1595 1596 drm_modeset_acquire_init(&ctx, 0); 1597 1598 retry_conn_enable: 1599 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1600 crtc, conn, 1601 preferred, 1602 &ctx); 1603 if (ret == -EDEADLK) { 1604 ret = drm_modeset_backoff(&ctx); 1605 if (!ret) 1606 goto retry_conn_enable; 1607 } 1608 KUNIT_EXPECT_EQ(test, ret, 0); 1609 1610 conn_state = conn->state; 1611 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1612 1613 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10); 1614 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1615 1616 drm_modeset_drop_locks(&ctx); 1617 drm_modeset_acquire_fini(&ctx); 1618 } 1619 1620 /* 1621 * Test that if: 1622 * - We have an HDMI connector supporting both RGB and YUV420 and up to 1623 * 12 bpc 1624 * - The chosen mode has a TMDS character rate higher than the display 1625 * supports in RGB/10bpc but lower than the display supports in 1626 * RGB/8bpc 1627 * - The chosen mode has a TMDS character rate lower than the display 1628 * supports in YUV420/12bpc. 1629 * 1630 * Then we will prefer to keep the RGB format with a lower bpc over 1631 * picking YUV420. 1632 */ 1633 static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420(struct kunit *test) 1634 { 1635 struct drm_atomic_helper_connector_hdmi_priv *priv; 1636 struct drm_modeset_acquire_ctx ctx; 1637 struct drm_connector_state *conn_state; 1638 struct drm_display_info *info; 1639 struct drm_display_mode *preferred; 1640 unsigned long long rate; 1641 struct drm_connector *conn; 1642 struct drm_device *drm; 1643 struct drm_crtc *crtc; 1644 int ret; 1645 1646 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1647 BIT(HDMI_COLORSPACE_RGB) | 1648 BIT(HDMI_COLORSPACE_YUV420), 1649 12, 1650 &dummy_connector_hdmi_funcs, 1651 test_edid_hdmi_4k_rgb_yuv420_dc_max_340mhz); 1652 KUNIT_ASSERT_NOT_NULL(test, priv); 1653 1654 drm = &priv->drm; 1655 crtc = priv->crtc; 1656 conn = &priv->connector; 1657 info = &conn->display_info; 1658 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1659 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1660 KUNIT_ASSERT_TRUE(test, conn->ycbcr_420_allowed); 1661 1662 preferred = find_preferred_mode(conn); 1663 KUNIT_ASSERT_NOT_NULL(test, preferred); 1664 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK); 1665 KUNIT_ASSERT_TRUE(test, drm_mode_is_420_also(info, preferred)); 1666 1667 rate = drm_hdmi_compute_mode_clock(preferred, 8, HDMI_COLORSPACE_RGB); 1668 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1669 1670 rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB); 1671 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1672 1673 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV420); 1674 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1675 1676 drm_modeset_acquire_init(&ctx, 0); 1677 1678 retry_conn_enable: 1679 ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, 1680 preferred, &ctx); 1681 if (ret == -EDEADLK) { 1682 ret = drm_modeset_backoff(&ctx); 1683 if (!ret) 1684 goto retry_conn_enable; 1685 } 1686 KUNIT_EXPECT_EQ(test, ret, 0); 1687 1688 conn_state = conn->state; 1689 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1690 1691 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 1692 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1693 1694 drm_modeset_drop_locks(&ctx); 1695 drm_modeset_acquire_fini(&ctx); 1696 } 1697 1698 /* 1699 * Test that if a driver supports only RGB, but the chosen mode can be 1700 * supported by the screen only in YUV420 output format, we end up with 1701 * unsuccessful fallback attempts. 1702 */ 1703 static void drm_test_check_driver_unsupported_fallback_yuv420(struct kunit *test) 1704 { 1705 struct drm_atomic_helper_connector_hdmi_priv *priv; 1706 struct drm_modeset_acquire_ctx ctx; 1707 struct drm_connector_state *conn_state; 1708 struct drm_crtc_state *crtc_state; 1709 struct drm_atomic_state *state; 1710 struct drm_display_info *info; 1711 struct drm_display_mode *preferred, *yuv420_only_mode; 1712 struct drm_connector *conn; 1713 struct drm_device *drm; 1714 struct drm_crtc *crtc; 1715 int ret; 1716 1717 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1718 BIT(HDMI_COLORSPACE_RGB), 1719 12, 1720 &dummy_connector_hdmi_funcs, 1721 test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz); 1722 KUNIT_ASSERT_NOT_NULL(test, priv); 1723 1724 drm = &priv->drm; 1725 crtc = priv->crtc; 1726 conn = &priv->connector; 1727 info = &conn->display_info; 1728 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1729 KUNIT_ASSERT_FALSE(test, conn->ycbcr_420_allowed); 1730 1731 preferred = find_preferred_mode(conn); 1732 KUNIT_ASSERT_NOT_NULL(test, preferred); 1733 KUNIT_ASSERT_FALSE(test, drm_mode_is_420_also(info, preferred)); 1734 1735 yuv420_only_mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95); 1736 KUNIT_ASSERT_NOT_NULL(test, yuv420_only_mode); 1737 KUNIT_ASSERT_TRUE(test, drm_mode_is_420_only(info, yuv420_only_mode)); 1738 1739 drm_modeset_acquire_init(&ctx, 0); 1740 1741 retry_conn_enable: 1742 ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn, 1743 preferred, &ctx); 1744 if (ret == -EDEADLK) { 1745 ret = drm_modeset_backoff(&ctx); 1746 if (!ret) 1747 goto retry_conn_enable; 1748 } 1749 KUNIT_EXPECT_EQ(test, ret, 0); 1750 1751 conn_state = conn->state; 1752 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1753 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1754 1755 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 1756 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 1757 1758 retry_crtc_state: 1759 crtc_state = drm_atomic_get_crtc_state(state, crtc); 1760 if (PTR_ERR(crtc_state) == -EDEADLK) { 1761 drm_atomic_state_clear(state); 1762 ret = drm_modeset_backoff(&ctx); 1763 if (!ret) 1764 goto retry_crtc_state; 1765 } 1766 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 1767 1768 ret = drm_atomic_set_mode_for_crtc(crtc_state, yuv420_only_mode); 1769 KUNIT_EXPECT_EQ(test, ret, 0); 1770 1771 ret = drm_atomic_check_only(state); 1772 if (ret == -EDEADLK) { 1773 drm_atomic_state_clear(state); 1774 ret = drm_modeset_backoff(&ctx); 1775 if (!ret) 1776 goto retry_crtc_state; 1777 } 1778 KUNIT_ASSERT_LT(test, ret, 0); 1779 1780 drm_modeset_drop_locks(&ctx); 1781 drm_modeset_acquire_fini(&ctx); 1782 } 1783 1784 /* 1785 * Test that if a driver and screen supports RGB and YUV formats, and we 1786 * try to set the VIC 1 mode, we end up with 8bpc RGB even if we could 1787 * have had a higher bpc. 1788 */ 1789 static void drm_test_check_output_bpc_format_vic_1(struct kunit *test) 1790 { 1791 struct drm_atomic_helper_connector_hdmi_priv *priv; 1792 struct drm_modeset_acquire_ctx ctx; 1793 struct drm_connector_state *conn_state; 1794 struct drm_display_info *info; 1795 struct drm_display_mode *mode; 1796 unsigned long long rate; 1797 struct drm_connector *conn; 1798 struct drm_device *drm; 1799 struct drm_crtc *crtc; 1800 int ret; 1801 1802 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1803 BIT(HDMI_COLORSPACE_RGB) | 1804 BIT(HDMI_COLORSPACE_YUV422) | 1805 BIT(HDMI_COLORSPACE_YUV444), 1806 12, 1807 &dummy_connector_hdmi_funcs, 1808 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); 1809 KUNIT_ASSERT_NOT_NULL(test, priv); 1810 1811 drm = &priv->drm; 1812 conn = &priv->connector; 1813 info = &conn->display_info; 1814 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1815 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1816 1817 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1); 1818 KUNIT_ASSERT_NOT_NULL(test, mode); 1819 1820 /* 1821 * NOTE: We can't use drm_hdmi_compute_mode_clock() 1822 * here because we're trying to get the rate of an invalid 1823 * configuration. 1824 * 1825 * Thus, we have to calculate the rate by hand. 1826 */ 1827 rate = mode->clock * 1500; 1828 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1829 1830 drm_modeset_acquire_init(&ctx, 0); 1831 1832 crtc = priv->crtc; 1833 1834 retry_conn_enable: 1835 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1836 crtc, conn, 1837 mode, 1838 &ctx); 1839 if (ret == -EDEADLK) { 1840 ret = drm_modeset_backoff(&ctx); 1841 if (!ret) 1842 goto retry_conn_enable; 1843 } 1844 KUNIT_EXPECT_EQ(test, ret, 0); 1845 1846 conn_state = conn->state; 1847 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1848 1849 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 1850 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1851 1852 drm_modeset_drop_locks(&ctx); 1853 drm_modeset_acquire_fini(&ctx); 1854 } 1855 1856 /* 1857 * Test that if a driver supports only RGB but the screen also supports 1858 * YUV formats, we only end up with an RGB format. 1859 */ 1860 static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test) 1861 { 1862 struct drm_atomic_helper_connector_hdmi_priv *priv; 1863 struct drm_modeset_acquire_ctx ctx; 1864 struct drm_connector_state *conn_state; 1865 struct drm_display_info *info; 1866 struct drm_display_mode *preferred; 1867 unsigned long long rate; 1868 struct drm_connector *conn; 1869 struct drm_device *drm; 1870 struct drm_crtc *crtc; 1871 int ret; 1872 1873 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1874 BIT(HDMI_COLORSPACE_RGB), 1875 12, 1876 &dummy_connector_hdmi_funcs, 1877 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz); 1878 KUNIT_ASSERT_NOT_NULL(test, priv); 1879 1880 drm = &priv->drm; 1881 crtc = priv->crtc; 1882 conn = &priv->connector; 1883 info = &conn->display_info; 1884 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1885 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1886 1887 preferred = find_preferred_mode(conn); 1888 KUNIT_ASSERT_NOT_NULL(test, preferred); 1889 1890 /* 1891 * We're making sure that YUV422 would be the preferred option 1892 * here: we're always favouring higher bpc, we can't have RGB 1893 * because the TMDS character rate exceeds the maximum supported 1894 * by the display, and YUV422 works for that display. 1895 * 1896 * But since the driver only supports RGB, we should fallback to 1897 * a lower bpc with RGB. 1898 */ 1899 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1900 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1901 1902 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); 1903 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1904 1905 drm_modeset_acquire_init(&ctx, 0); 1906 1907 retry_conn_enable: 1908 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1909 crtc, conn, 1910 preferred, 1911 &ctx); 1912 if (ret == -EDEADLK) { 1913 ret = drm_modeset_backoff(&ctx); 1914 if (!ret) 1915 goto retry_conn_enable; 1916 } 1917 KUNIT_EXPECT_EQ(test, ret, 0); 1918 1919 conn_state = conn->state; 1920 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1921 1922 KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12); 1923 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1924 1925 drm_modeset_drop_locks(&ctx); 1926 drm_modeset_acquire_fini(&ctx); 1927 } 1928 1929 /* 1930 * Test that if a screen supports only RGB but the driver also supports 1931 * YUV formats, we only end up with an RGB format. 1932 */ 1933 static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test) 1934 { 1935 struct drm_atomic_helper_connector_hdmi_priv *priv; 1936 struct drm_modeset_acquire_ctx ctx; 1937 struct drm_connector_state *conn_state; 1938 struct drm_display_info *info; 1939 struct drm_display_mode *preferred; 1940 unsigned long long rate; 1941 struct drm_connector *conn; 1942 struct drm_device *drm; 1943 struct drm_crtc *crtc; 1944 int ret; 1945 1946 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 1947 BIT(HDMI_COLORSPACE_RGB) | 1948 BIT(HDMI_COLORSPACE_YUV422) | 1949 BIT(HDMI_COLORSPACE_YUV444), 1950 12, 1951 &dummy_connector_hdmi_funcs, 1952 test_edid_hdmi_1080p_rgb_max_200mhz); 1953 KUNIT_ASSERT_NOT_NULL(test, priv); 1954 1955 drm = &priv->drm; 1956 crtc = priv->crtc; 1957 conn = &priv->connector; 1958 info = &conn->display_info; 1959 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 1960 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 1961 1962 preferred = find_preferred_mode(conn); 1963 KUNIT_ASSERT_NOT_NULL(test, preferred); 1964 1965 /* 1966 * We're making sure that YUV422 would be the preferred option 1967 * here: we're always favouring higher bpc, we can't have RGB 1968 * because the TMDS character rate exceeds the maximum supported 1969 * by the display, and YUV422 works for that display. 1970 * 1971 * But since the display only supports RGB, we should fallback to 1972 * a lower bpc with RGB. 1973 */ 1974 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 1975 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000); 1976 1977 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422); 1978 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 1979 1980 drm_modeset_acquire_init(&ctx, 0); 1981 1982 retry_conn_enable: 1983 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 1984 crtc, conn, 1985 preferred, 1986 &ctx); 1987 if (ret == -EDEADLK) { 1988 ret = drm_modeset_backoff(&ctx); 1989 if (!ret) 1990 goto retry_conn_enable; 1991 } 1992 KUNIT_EXPECT_EQ(test, ret, 0); 1993 1994 conn_state = conn->state; 1995 KUNIT_ASSERT_NOT_NULL(test, conn_state); 1996 1997 KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12); 1998 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 1999 2000 drm_modeset_drop_locks(&ctx); 2001 drm_modeset_acquire_fini(&ctx); 2002 } 2003 2004 /* 2005 * Test that if a display supports higher bpc but the driver only 2006 * supports 8 bpc, we only end up with 8 bpc even if we could have had a 2007 * higher bpc. 2008 */ 2009 static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test) 2010 { 2011 struct drm_atomic_helper_connector_hdmi_priv *priv; 2012 struct drm_modeset_acquire_ctx ctx; 2013 struct drm_connector_state *conn_state; 2014 struct drm_display_info *info; 2015 struct drm_display_mode *preferred; 2016 unsigned long long rate; 2017 struct drm_connector *conn; 2018 struct drm_device *drm; 2019 struct drm_crtc *crtc; 2020 int ret; 2021 2022 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2023 BIT(HDMI_COLORSPACE_RGB), 2024 8, 2025 &dummy_connector_hdmi_funcs, 2026 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz); 2027 KUNIT_ASSERT_NOT_NULL(test, priv); 2028 2029 drm = &priv->drm; 2030 crtc = priv->crtc; 2031 conn = &priv->connector; 2032 info = &conn->display_info; 2033 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 2034 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 2035 2036 preferred = find_preferred_mode(conn); 2037 KUNIT_ASSERT_NOT_NULL(test, preferred); 2038 2039 /* 2040 * We're making sure that we have headroom on the TMDS character 2041 * clock to actually use 12bpc. 2042 */ 2043 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 2044 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 2045 2046 drm_modeset_acquire_init(&ctx, 0); 2047 2048 retry_conn_enable: 2049 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 2050 crtc, conn, 2051 preferred, 2052 &ctx); 2053 if (ret == -EDEADLK) { 2054 ret = drm_modeset_backoff(&ctx); 2055 if (!ret) 2056 goto retry_conn_enable; 2057 } 2058 KUNIT_EXPECT_EQ(test, ret, 0); 2059 2060 conn_state = conn->state; 2061 KUNIT_ASSERT_NOT_NULL(test, conn_state); 2062 2063 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 2064 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 2065 2066 drm_modeset_drop_locks(&ctx); 2067 drm_modeset_acquire_fini(&ctx); 2068 } 2069 2070 /* 2071 * Test that if a driver supports higher bpc but the display only 2072 * supports 8 bpc, we only end up with 8 bpc even if we could have had a 2073 * higher bpc. 2074 */ 2075 static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *test) 2076 { 2077 struct drm_atomic_helper_connector_hdmi_priv *priv; 2078 struct drm_modeset_acquire_ctx ctx; 2079 struct drm_connector_state *conn_state; 2080 struct drm_display_info *info; 2081 struct drm_display_mode *preferred; 2082 unsigned long long rate; 2083 struct drm_connector *conn; 2084 struct drm_device *drm; 2085 struct drm_crtc *crtc; 2086 int ret; 2087 2088 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2089 BIT(HDMI_COLORSPACE_RGB) | 2090 BIT(HDMI_COLORSPACE_YUV422) | 2091 BIT(HDMI_COLORSPACE_YUV444), 2092 12, 2093 &dummy_connector_hdmi_funcs, 2094 test_edid_hdmi_1080p_rgb_max_340mhz); 2095 KUNIT_ASSERT_NOT_NULL(test, priv); 2096 2097 drm = &priv->drm; 2098 crtc = priv->crtc; 2099 conn = &priv->connector; 2100 info = &conn->display_info; 2101 KUNIT_ASSERT_TRUE(test, info->is_hdmi); 2102 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0); 2103 2104 preferred = find_preferred_mode(conn); 2105 KUNIT_ASSERT_NOT_NULL(test, preferred); 2106 2107 /* 2108 * We're making sure that we have headroom on the TMDS character 2109 * clock to actually use 12bpc. 2110 */ 2111 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB); 2112 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000); 2113 2114 drm_modeset_acquire_init(&ctx, 0); 2115 2116 retry_conn_enable: 2117 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 2118 crtc, conn, 2119 preferred, 2120 &ctx); 2121 if (ret == -EDEADLK) { 2122 ret = drm_modeset_backoff(&ctx); 2123 if (!ret) 2124 goto retry_conn_enable; 2125 } 2126 KUNIT_EXPECT_EQ(test, ret, 0); 2127 2128 conn_state = conn->state; 2129 KUNIT_ASSERT_NOT_NULL(test, conn_state); 2130 2131 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8); 2132 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB); 2133 2134 drm_modeset_drop_locks(&ctx); 2135 drm_modeset_acquire_fini(&ctx); 2136 } 2137 2138 /* Test that atomic check succeeds when disabling a connector. */ 2139 static void drm_test_check_disable_connector(struct kunit *test) 2140 { 2141 struct drm_atomic_helper_connector_hdmi_priv *priv; 2142 struct drm_modeset_acquire_ctx ctx; 2143 struct drm_connector_state *conn_state; 2144 struct drm_crtc_state *crtc_state; 2145 struct drm_atomic_state *state; 2146 struct drm_display_mode *preferred; 2147 struct drm_connector *conn; 2148 struct drm_device *drm; 2149 struct drm_crtc *crtc; 2150 int ret; 2151 2152 priv = drm_kunit_helper_connector_hdmi_init(test, 2153 BIT(HDMI_COLORSPACE_RGB), 2154 8); 2155 KUNIT_ASSERT_NOT_NULL(test, priv); 2156 2157 drm_modeset_acquire_init(&ctx, 0); 2158 2159 conn = &priv->connector; 2160 preferred = find_preferred_mode(conn); 2161 KUNIT_ASSERT_NOT_NULL(test, preferred); 2162 2163 drm = &priv->drm; 2164 crtc = priv->crtc; 2165 2166 retry_conn_enable: 2167 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 2168 crtc, conn, 2169 preferred, 2170 &ctx); 2171 if (ret == -EDEADLK) { 2172 ret = drm_modeset_backoff(&ctx); 2173 if (!ret) 2174 goto retry_conn_enable; 2175 } 2176 KUNIT_ASSERT_EQ(test, ret, 0); 2177 2178 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 2179 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 2180 2181 crtc_state = drm_atomic_get_crtc_state(state, crtc); 2182 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 2183 2184 crtc_state->active = false; 2185 ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL); 2186 KUNIT_EXPECT_EQ(test, ret, 0); 2187 2188 conn_state = drm_atomic_get_connector_state(state, conn); 2189 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state); 2190 2191 ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); 2192 KUNIT_EXPECT_EQ(test, ret, 0); 2193 2194 ret = drm_atomic_check_only(state); 2195 KUNIT_ASSERT_EQ(test, ret, 0); 2196 2197 drm_modeset_drop_locks(&ctx); 2198 drm_modeset_acquire_fini(&ctx); 2199 } 2200 2201 static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = { 2202 KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode), 2203 KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode_vic_1), 2204 KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode), 2205 KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode_vic_1), 2206 KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode), 2207 KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode_vic_1), 2208 KUNIT_CASE_PARAM(drm_test_check_broadcast_rgb_cea_mode_yuv420, 2209 check_broadcast_rgb_cea_mode_yuv420_gen_params), 2210 KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_changed), 2211 KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_not_changed), 2212 KUNIT_CASE(drm_test_check_disable_connector), 2213 KUNIT_CASE(drm_test_check_hdmi_funcs_reject_rate), 2214 KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_rgb), 2215 KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_yuv420), 2216 KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422), 2217 KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420), 2218 KUNIT_CASE(drm_test_check_driver_unsupported_fallback_yuv420), 2219 KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_changed), 2220 KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_not_changed), 2221 KUNIT_CASE(drm_test_check_output_bpc_dvi), 2222 KUNIT_CASE(drm_test_check_output_bpc_format_vic_1), 2223 KUNIT_CASE(drm_test_check_output_bpc_format_display_8bpc_only), 2224 KUNIT_CASE(drm_test_check_output_bpc_format_display_rgb_only), 2225 KUNIT_CASE(drm_test_check_output_bpc_format_driver_8bpc_only), 2226 KUNIT_CASE(drm_test_check_output_bpc_format_driver_rgb_only), 2227 KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_8bpc), 2228 KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_10bpc), 2229 KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_12bpc), 2230 /* 2231 * TODO: We should have tests to check that a change in the 2232 * format triggers a CRTC mode change just like we do for the 2233 * RGB Quantization and BPC. 2234 * 2235 * However, we don't have any way to control which format gets 2236 * picked up aside from changing the BPC or mode which would 2237 * already trigger a mode change. 2238 */ 2239 { } 2240 }; 2241 2242 static struct kunit_suite drm_atomic_helper_connector_hdmi_check_test_suite = { 2243 .name = "drm_atomic_helper_connector_hdmi_check", 2244 .test_cases = drm_atomic_helper_connector_hdmi_check_tests, 2245 }; 2246 2247 /* 2248 * Test that the value of the Broadcast RGB property out of reset is set 2249 * to auto. 2250 */ 2251 static void drm_test_check_broadcast_rgb_value(struct kunit *test) 2252 { 2253 struct drm_atomic_helper_connector_hdmi_priv *priv; 2254 struct drm_connector_state *conn_state; 2255 struct drm_connector *conn; 2256 2257 priv = drm_kunit_helper_connector_hdmi_init(test, 2258 BIT(HDMI_COLORSPACE_RGB), 2259 8); 2260 KUNIT_ASSERT_NOT_NULL(test, priv); 2261 2262 conn = &priv->connector; 2263 conn_state = conn->state; 2264 KUNIT_EXPECT_EQ(test, conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_AUTO); 2265 } 2266 2267 /* 2268 * Test that if the connector was initialised with a maximum bpc of 8, 2269 * the value of the max_bpc and max_requested_bpc properties out of 2270 * reset are also set to 8, and output_bpc is set to 0 and will be 2271 * filled at atomic_check time. 2272 */ 2273 static void drm_test_check_bpc_8_value(struct kunit *test) 2274 { 2275 struct drm_atomic_helper_connector_hdmi_priv *priv; 2276 struct drm_connector_state *conn_state; 2277 struct drm_connector *conn; 2278 2279 priv = drm_kunit_helper_connector_hdmi_init(test, 2280 BIT(HDMI_COLORSPACE_RGB), 2281 8); 2282 KUNIT_ASSERT_NOT_NULL(test, priv); 2283 2284 conn = &priv->connector; 2285 conn_state = conn->state; 2286 KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 8); 2287 KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 8); 2288 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0); 2289 } 2290 2291 /* 2292 * Test that if the connector was initialised with a maximum bpc of 10, 2293 * the value of the max_bpc and max_requested_bpc properties out of 2294 * reset are also set to 10, and output_bpc is set to 0 and will be 2295 * filled at atomic_check time. 2296 */ 2297 static void drm_test_check_bpc_10_value(struct kunit *test) 2298 { 2299 struct drm_atomic_helper_connector_hdmi_priv *priv; 2300 struct drm_connector_state *conn_state; 2301 struct drm_connector *conn; 2302 2303 priv = drm_kunit_helper_connector_hdmi_init(test, 2304 BIT(HDMI_COLORSPACE_RGB), 2305 10); 2306 KUNIT_ASSERT_NOT_NULL(test, priv); 2307 2308 conn = &priv->connector; 2309 conn_state = conn->state; 2310 KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 10); 2311 KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 10); 2312 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0); 2313 } 2314 2315 /* 2316 * Test that if the connector was initialised with a maximum bpc of 12, 2317 * the value of the max_bpc and max_requested_bpc properties out of 2318 * reset are also set to 12, and output_bpc is set to 0 and will be 2319 * filled at atomic_check time. 2320 */ 2321 static void drm_test_check_bpc_12_value(struct kunit *test) 2322 { 2323 struct drm_atomic_helper_connector_hdmi_priv *priv; 2324 struct drm_connector_state *conn_state; 2325 struct drm_connector *conn; 2326 2327 priv = drm_kunit_helper_connector_hdmi_init(test, 2328 BIT(HDMI_COLORSPACE_RGB), 2329 12); 2330 KUNIT_ASSERT_NOT_NULL(test, priv); 2331 2332 conn = &priv->connector; 2333 conn_state = conn->state; 2334 KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 12); 2335 KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 12); 2336 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0); 2337 } 2338 2339 /* 2340 * Test that the value of the output format property out of reset is set 2341 * to RGB, even if the driver supports more than that. 2342 */ 2343 static void drm_test_check_format_value(struct kunit *test) 2344 { 2345 struct drm_atomic_helper_connector_hdmi_priv *priv; 2346 struct drm_connector_state *conn_state; 2347 struct drm_connector *conn; 2348 2349 priv = drm_kunit_helper_connector_hdmi_init(test, 2350 BIT(HDMI_COLORSPACE_RGB) | 2351 BIT(HDMI_COLORSPACE_YUV422) | 2352 BIT(HDMI_COLORSPACE_YUV444), 2353 8); 2354 KUNIT_ASSERT_NOT_NULL(test, priv); 2355 2356 conn = &priv->connector; 2357 conn_state = conn->state; 2358 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, 0); 2359 } 2360 2361 /* 2362 * Test that the value of the output format property out of reset is set 2363 * to 0, and will be computed at atomic_check time. 2364 */ 2365 static void drm_test_check_tmds_char_value(struct kunit *test) 2366 { 2367 struct drm_atomic_helper_connector_hdmi_priv *priv; 2368 struct drm_connector_state *conn_state; 2369 struct drm_connector *conn; 2370 2371 priv = drm_kunit_helper_connector_hdmi_init(test, 2372 BIT(HDMI_COLORSPACE_RGB) | 2373 BIT(HDMI_COLORSPACE_YUV422) | 2374 BIT(HDMI_COLORSPACE_YUV444), 2375 12); 2376 KUNIT_ASSERT_NOT_NULL(test, priv); 2377 2378 conn = &priv->connector; 2379 conn_state = conn->state; 2380 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, 0); 2381 } 2382 2383 static struct kunit_case drm_atomic_helper_connector_hdmi_reset_tests[] = { 2384 KUNIT_CASE(drm_test_check_broadcast_rgb_value), 2385 KUNIT_CASE(drm_test_check_bpc_8_value), 2386 KUNIT_CASE(drm_test_check_bpc_10_value), 2387 KUNIT_CASE(drm_test_check_bpc_12_value), 2388 KUNIT_CASE(drm_test_check_format_value), 2389 KUNIT_CASE(drm_test_check_tmds_char_value), 2390 { } 2391 }; 2392 2393 static struct kunit_suite drm_atomic_helper_connector_hdmi_reset_test_suite = { 2394 .name = "drm_atomic_helper_connector_hdmi_reset", 2395 .test_cases = drm_atomic_helper_connector_hdmi_reset_tests, 2396 }; 2397 2398 /* 2399 * Test that the default behaviour for drm_hdmi_connector_mode_valid() is not 2400 * to reject any modes. Pass a correct EDID and verify that preferred mode 2401 * matches the expectations (1080p). 2402 */ 2403 static void drm_test_check_mode_valid(struct kunit *test) 2404 { 2405 struct drm_atomic_helper_connector_hdmi_priv *priv; 2406 struct drm_connector *conn; 2407 struct drm_display_mode *preferred; 2408 2409 priv = drm_kunit_helper_connector_hdmi_init(test, 2410 BIT(HDMI_COLORSPACE_RGB), 2411 8); 2412 KUNIT_ASSERT_NOT_NULL(test, priv); 2413 2414 conn = &priv->connector; 2415 preferred = find_preferred_mode(conn); 2416 KUNIT_ASSERT_NOT_NULL(test, preferred); 2417 2418 KUNIT_EXPECT_EQ(test, preferred->hdisplay, 1920); 2419 KUNIT_EXPECT_EQ(test, preferred->vdisplay, 1080); 2420 KUNIT_EXPECT_EQ(test, preferred->clock, 148500); 2421 } 2422 2423 /* 2424 * Test that the drm_hdmi_connector_mode_valid() will reject modes depending on 2425 * the .tmds_char_rate_valid() behaviour. 2426 * Pass a correct EDID and verify that high-rate modes are filtered. 2427 */ 2428 static void drm_test_check_mode_valid_reject_rate(struct kunit *test) 2429 { 2430 struct drm_atomic_helper_connector_hdmi_priv *priv; 2431 struct drm_display_mode *preferred; 2432 2433 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2434 BIT(HDMI_COLORSPACE_RGB), 2435 8, 2436 &reject_100mhz_connector_hdmi_funcs, 2437 test_edid_hdmi_1080p_rgb_max_200mhz); 2438 KUNIT_ASSERT_NOT_NULL(test, priv); 2439 2440 /* 2441 * Unlike the drm_test_check_mode_valid() here 1080p is rejected, but 2442 * 480p is allowed. 2443 */ 2444 preferred = find_preferred_mode(&priv->connector); 2445 KUNIT_ASSERT_NOT_NULL(test, preferred); 2446 KUNIT_EXPECT_EQ(test, preferred->hdisplay, 640); 2447 KUNIT_EXPECT_EQ(test, preferred->vdisplay, 480); 2448 KUNIT_EXPECT_EQ(test, preferred->clock, 25200); 2449 } 2450 2451 /* 2452 * Test that the drm_hdmi_connector_mode_valid() will not mark any modes as 2453 * valid if .tmds_char_rate_valid() rejects all of them. Pass a correct EDID 2454 * and verify that there is no preferred mode and no modes were set for the 2455 * connector. 2456 */ 2457 static void drm_test_check_mode_valid_reject(struct kunit *test) 2458 { 2459 struct drm_atomic_helper_connector_hdmi_priv *priv; 2460 struct drm_connector *conn; 2461 struct drm_display_mode *preferred; 2462 unsigned char no_edid[] = {}; 2463 int ret; 2464 2465 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2466 BIT(HDMI_COLORSPACE_RGB), 2467 8, 2468 &reject_connector_hdmi_funcs, 2469 no_edid); 2470 KUNIT_ASSERT_NOT_NULL(test, priv); 2471 2472 conn = &priv->connector; 2473 2474 /* should reject all modes */ 2475 ret = set_connector_edid(test, conn, 2476 test_edid_hdmi_1080p_rgb_max_200mhz, 2477 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz)); 2478 KUNIT_ASSERT_EQ(test, ret, 0); 2479 2480 preferred = find_preferred_mode(conn); 2481 KUNIT_ASSERT_NULL(test, preferred); 2482 } 2483 2484 /* 2485 * Test that the drm_hdmi_connector_mode_valid() will reject modes that don't 2486 * pass the info.max_tmds_clock filter. Pass crafted EDID and verify that 2487 * high-rate modes are filtered. 2488 */ 2489 static void drm_test_check_mode_valid_reject_max_clock(struct kunit *test) 2490 { 2491 struct drm_atomic_helper_connector_hdmi_priv *priv; 2492 struct drm_connector *conn; 2493 struct drm_display_mode *preferred; 2494 2495 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2496 BIT(HDMI_COLORSPACE_RGB), 2497 8, 2498 &dummy_connector_hdmi_funcs, 2499 test_edid_hdmi_1080p_rgb_max_100mhz); 2500 KUNIT_ASSERT_NOT_NULL(test, priv); 2501 2502 conn = &priv->connector; 2503 KUNIT_ASSERT_EQ(test, conn->display_info.max_tmds_clock, 100 * 1000); 2504 2505 preferred = find_preferred_mode(conn); 2506 KUNIT_ASSERT_NOT_NULL(test, preferred); 2507 KUNIT_EXPECT_EQ(test, preferred->hdisplay, 640); 2508 KUNIT_EXPECT_EQ(test, preferred->vdisplay, 480); 2509 KUNIT_EXPECT_EQ(test, preferred->clock, 25200); 2510 } 2511 2512 static struct kunit_case drm_atomic_helper_connector_hdmi_mode_valid_tests[] = { 2513 KUNIT_CASE(drm_test_check_mode_valid), 2514 KUNIT_CASE(drm_test_check_mode_valid_reject), 2515 KUNIT_CASE(drm_test_check_mode_valid_reject_rate), 2516 KUNIT_CASE(drm_test_check_mode_valid_reject_max_clock), 2517 { } 2518 }; 2519 2520 static struct kunit_suite drm_atomic_helper_connector_hdmi_mode_valid_test_suite = { 2521 .name = "drm_atomic_helper_connector_hdmi_mode_valid", 2522 .test_cases = drm_atomic_helper_connector_hdmi_mode_valid_tests, 2523 }; 2524 2525 /* 2526 * Test that the default behaviour works without errors. We expect that 2527 * infoframe-related hooks are called and there are no errors raised. 2528 */ 2529 static void drm_test_check_infoframes(struct kunit *test) 2530 { 2531 struct drm_atomic_helper_connector_hdmi_priv *priv; 2532 struct drm_modeset_acquire_ctx ctx; 2533 struct drm_crtc_state *crtc_state; 2534 struct drm_atomic_state *state; 2535 struct drm_display_mode *preferred; 2536 struct drm_connector *conn; 2537 struct drm_device *drm; 2538 struct drm_crtc *crtc; 2539 int old_hdmi_update_failures; 2540 int ret; 2541 2542 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2543 BIT(HDMI_COLORSPACE_RGB), 2544 8, 2545 &dummy_connector_hdmi_funcs, 2546 test_edid_hdmi_1080p_rgb_max_200mhz); 2547 KUNIT_ASSERT_NOT_NULL(test, priv); 2548 2549 drm = &priv->drm; 2550 crtc = priv->crtc; 2551 conn = &priv->connector; 2552 2553 preferred = find_preferred_mode(conn); 2554 KUNIT_ASSERT_NOT_NULL(test, preferred); 2555 2556 drm_modeset_acquire_init(&ctx, 0); 2557 2558 retry_conn_enable: 2559 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 2560 crtc, conn, 2561 preferred, 2562 &ctx); 2563 if (ret == -EDEADLK) { 2564 ret = drm_modeset_backoff(&ctx); 2565 if (!ret) 2566 goto retry_conn_enable; 2567 } 2568 KUNIT_ASSERT_EQ(test, ret, 0); 2569 2570 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 2571 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 2572 2573 retry_crtc_state: 2574 crtc_state = drm_atomic_get_crtc_state(state, crtc); 2575 if (PTR_ERR(crtc_state) == -EDEADLK) { 2576 drm_atomic_state_clear(state); 2577 ret = drm_modeset_backoff(&ctx); 2578 if (!ret) 2579 goto retry_crtc_state; 2580 } 2581 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 2582 2583 crtc_state->mode_changed = true; 2584 2585 old_hdmi_update_failures = priv->hdmi_update_failures; 2586 2587 ret = drm_atomic_check_only(state); 2588 if (ret == -EDEADLK) { 2589 drm_atomic_state_clear(state); 2590 ret = drm_modeset_backoff(&ctx); 2591 if (!ret) 2592 goto retry_crtc_state; 2593 } 2594 KUNIT_ASSERT_EQ(test, ret, 0); 2595 2596 ret = drm_atomic_commit(state); 2597 if (ret == -EDEADLK) { 2598 drm_atomic_state_clear(state); 2599 ret = drm_modeset_backoff(&ctx); 2600 if (!ret) 2601 goto retry_crtc_state; 2602 } 2603 KUNIT_ASSERT_EQ(test, ret, 0); 2604 2605 KUNIT_EXPECT_GE(test, old_hdmi_update_failures, priv->hdmi_update_failures); 2606 2607 drm_modeset_drop_locks(&ctx); 2608 drm_modeset_acquire_fini(&ctx); 2609 } 2610 2611 static int reject_infoframe_write_infoframe(struct drm_connector *connector, 2612 const u8 *buffer, size_t len) 2613 { 2614 return -EOPNOTSUPP; 2615 } 2616 2617 static const struct drm_connector_hdmi_funcs reject_avi_infoframe_hdmi_funcs = { 2618 .avi = { 2619 .clear_infoframe = accept_infoframe_clear_infoframe, 2620 .write_infoframe = reject_infoframe_write_infoframe, 2621 }, 2622 .hdmi = { 2623 .clear_infoframe = accept_infoframe_clear_infoframe, 2624 .write_infoframe = accept_infoframe_write_infoframe, 2625 }, 2626 }; 2627 2628 /* 2629 * Test that the rejection of AVI InfoFrame results in the failure of 2630 * drm_atomic_helper_connector_hdmi_update_infoframes(). 2631 */ 2632 static void drm_test_check_reject_avi_infoframe(struct kunit *test) 2633 { 2634 struct drm_atomic_helper_connector_hdmi_priv *priv; 2635 struct drm_modeset_acquire_ctx ctx; 2636 struct drm_atomic_state *state; 2637 struct drm_crtc_state *crtc_state; 2638 struct drm_display_mode *preferred; 2639 struct drm_connector *conn; 2640 struct drm_device *drm; 2641 struct drm_crtc *crtc; 2642 int old_hdmi_update_failures; 2643 int ret; 2644 2645 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2646 BIT(HDMI_COLORSPACE_RGB), 2647 8, 2648 &reject_avi_infoframe_hdmi_funcs, 2649 test_edid_hdmi_1080p_rgb_max_200mhz); 2650 KUNIT_ASSERT_NOT_NULL(test, priv); 2651 2652 drm = &priv->drm; 2653 crtc = priv->crtc; 2654 conn = &priv->connector; 2655 2656 preferred = find_preferred_mode(conn); 2657 KUNIT_ASSERT_NOT_NULL(test, preferred); 2658 2659 drm_modeset_acquire_init(&ctx, 0); 2660 2661 retry_conn_enable: 2662 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 2663 crtc, conn, 2664 preferred, 2665 &ctx); 2666 if (ret == -EDEADLK) { 2667 ret = drm_modeset_backoff(&ctx); 2668 if (!ret) 2669 goto retry_conn_enable; 2670 } 2671 KUNIT_ASSERT_EQ(test, ret, 0); 2672 2673 drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs); 2674 2675 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 2676 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 2677 2678 retry_crtc_state: 2679 crtc_state = drm_atomic_get_crtc_state(state, crtc); 2680 if (PTR_ERR(crtc_state) == -EDEADLK) { 2681 drm_atomic_state_clear(state); 2682 ret = drm_modeset_backoff(&ctx); 2683 if (!ret) 2684 goto retry_crtc_state; 2685 } 2686 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 2687 2688 crtc_state->mode_changed = true; 2689 2690 old_hdmi_update_failures = priv->hdmi_update_failures; 2691 2692 ret = drm_atomic_check_only(state); 2693 if (ret == -EDEADLK) { 2694 drm_atomic_state_clear(state); 2695 ret = drm_modeset_backoff(&ctx); 2696 if (!ret) 2697 goto retry_crtc_state; 2698 } 2699 KUNIT_ASSERT_EQ(test, ret, 0); 2700 2701 ret = drm_atomic_commit(state); 2702 if (ret == -EDEADLK) { 2703 drm_atomic_state_clear(state); 2704 ret = drm_modeset_backoff(&ctx); 2705 if (!ret) 2706 goto retry_crtc_state; 2707 } 2708 KUNIT_ASSERT_EQ(test, ret, 0); 2709 2710 KUNIT_EXPECT_NE(test, old_hdmi_update_failures, priv->hdmi_update_failures); 2711 2712 drm_modeset_drop_locks(&ctx); 2713 drm_modeset_acquire_fini(&ctx); 2714 } 2715 2716 static const struct drm_connector_hdmi_funcs reject_hdr_infoframe_hdmi_funcs = { 2717 .avi = { 2718 .clear_infoframe = accept_infoframe_clear_infoframe, 2719 .write_infoframe = accept_infoframe_write_infoframe, 2720 }, 2721 .hdmi = { 2722 .clear_infoframe = accept_infoframe_clear_infoframe, 2723 .write_infoframe = accept_infoframe_write_infoframe, 2724 }, 2725 .hdr_drm = { 2726 .clear_infoframe = accept_infoframe_clear_infoframe, 2727 .write_infoframe = reject_infoframe_write_infoframe, 2728 }, 2729 }; 2730 2731 /* 2732 * Test that the HDR InfoFrame isn't programmed in 2733 * drm_atomic_helper_connector_hdmi_update_infoframes() if the max_bpc is 8. 2734 */ 2735 static void drm_test_check_reject_hdr_infoframe_bpc_8(struct kunit *test) 2736 { 2737 struct drm_atomic_helper_connector_hdmi_priv *priv; 2738 struct drm_modeset_acquire_ctx ctx; 2739 struct drm_atomic_state *state; 2740 struct drm_connector_state *new_conn_state; 2741 struct drm_crtc_state *crtc_state; 2742 struct drm_display_mode *preferred; 2743 struct drm_connector *conn; 2744 struct drm_device *drm; 2745 struct drm_crtc *crtc; 2746 int old_hdmi_update_failures; 2747 int ret; 2748 2749 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2750 BIT(HDMI_COLORSPACE_RGB), 2751 8, 2752 &reject_hdr_infoframe_hdmi_funcs, 2753 test_edid_hdmi_1080p_rgb_max_200mhz_hdr); 2754 KUNIT_ASSERT_NOT_NULL(test, priv); 2755 2756 drm = &priv->drm; 2757 crtc = priv->crtc; 2758 conn = &priv->connector; 2759 2760 preferred = find_preferred_mode(conn); 2761 KUNIT_ASSERT_NOT_NULL(test, preferred); 2762 2763 drm_modeset_acquire_init(&ctx, 0); 2764 2765 retry_conn_enable: 2766 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 2767 crtc, conn, 2768 preferred, 2769 &ctx); 2770 if (ret == -EDEADLK) { 2771 ret = drm_modeset_backoff(&ctx); 2772 if (!ret) 2773 goto retry_conn_enable; 2774 } 2775 KUNIT_ASSERT_EQ(test, ret, 0); 2776 2777 drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs); 2778 2779 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 2780 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 2781 2782 retry_conn_state: 2783 new_conn_state = drm_atomic_get_connector_state(state, conn); 2784 if (PTR_ERR(new_conn_state) == -EDEADLK) { 2785 drm_atomic_state_clear(state); 2786 ret = drm_modeset_backoff(&ctx); 2787 if (!ret) 2788 goto retry_conn_state; 2789 } 2790 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 2791 2792 crtc_state = drm_atomic_get_crtc_state(state, crtc); 2793 if (PTR_ERR(crtc_state) == -EDEADLK) { 2794 drm_atomic_state_clear(state); 2795 ret = drm_modeset_backoff(&ctx); 2796 if (!ret) 2797 goto retry_conn_state; 2798 } 2799 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 2800 2801 /* Verify that there is no HDR property, so "userspace" can't set it. */ 2802 for (int i = 0; i < conn->base.properties->count; i++) 2803 KUNIT_ASSERT_PTR_NE(test, 2804 drm->mode_config.hdr_output_metadata_property, 2805 conn->base.properties->properties[i]); 2806 2807 crtc_state->mode_changed = true; 2808 2809 old_hdmi_update_failures = priv->hdmi_update_failures; 2810 2811 ret = drm_atomic_check_only(state); 2812 if (ret == -EDEADLK) { 2813 drm_atomic_state_clear(state); 2814 ret = drm_modeset_backoff(&ctx); 2815 if (!ret) 2816 goto retry_conn_state; 2817 } 2818 KUNIT_ASSERT_EQ(test, ret, 0); 2819 2820 ret = drm_atomic_commit(state); 2821 if (ret == -EDEADLK) { 2822 drm_atomic_state_clear(state); 2823 ret = drm_modeset_backoff(&ctx); 2824 if (!ret) 2825 goto retry_conn_state; 2826 } 2827 KUNIT_ASSERT_EQ(test, ret, 0); 2828 2829 KUNIT_EXPECT_EQ(test, old_hdmi_update_failures, priv->hdmi_update_failures); 2830 2831 new_conn_state = conn->state; 2832 KUNIT_ASSERT_NOT_NULL(test, new_conn_state); 2833 2834 KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.output_bpc, 8); 2835 KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.infoframes.hdr_drm.set, false); 2836 2837 drm_modeset_drop_locks(&ctx); 2838 drm_modeset_acquire_fini(&ctx); 2839 } 2840 2841 /* 2842 * Test that the rejection of HDR InfoFrame results in the failure of 2843 * drm_atomic_helper_connector_hdmi_update_infoframes() in the high bpc is 2844 * supported. 2845 */ 2846 static void drm_test_check_reject_hdr_infoframe_bpc_10(struct kunit *test) 2847 { 2848 struct drm_atomic_helper_connector_hdmi_priv *priv; 2849 struct drm_modeset_acquire_ctx ctx; 2850 struct drm_atomic_state *state; 2851 struct drm_connector_state *new_conn_state; 2852 struct drm_crtc_state *crtc_state; 2853 struct drm_display_mode *preferred; 2854 struct drm_connector *conn; 2855 struct drm_device *drm; 2856 struct drm_crtc *crtc; 2857 int old_hdmi_update_failures; 2858 struct hdr_output_metadata hdr_data; 2859 struct drm_property_blob *hdr_blob; 2860 bool replaced; 2861 int ret; 2862 2863 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2864 BIT(HDMI_COLORSPACE_RGB), 2865 10, 2866 &reject_hdr_infoframe_hdmi_funcs, 2867 test_edid_hdmi_1080p_rgb_max_200mhz_hdr); 2868 KUNIT_ASSERT_NOT_NULL(test, priv); 2869 2870 drm = &priv->drm; 2871 crtc = priv->crtc; 2872 conn = &priv->connector; 2873 2874 preferred = find_preferred_mode(conn); 2875 KUNIT_ASSERT_NOT_NULL(test, preferred); 2876 2877 drm_modeset_acquire_init(&ctx, 0); 2878 2879 retry_conn_enable: 2880 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 2881 crtc, conn, 2882 preferred, 2883 &ctx); 2884 if (ret == -EDEADLK) { 2885 ret = drm_modeset_backoff(&ctx); 2886 if (!ret) 2887 goto retry_conn_enable; 2888 } 2889 KUNIT_ASSERT_EQ(test, ret, 0); 2890 2891 drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs); 2892 2893 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 2894 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 2895 2896 retry_conn_state: 2897 new_conn_state = drm_atomic_get_connector_state(state, conn); 2898 if (PTR_ERR(new_conn_state) == -EDEADLK) { 2899 drm_atomic_state_clear(state); 2900 ret = drm_modeset_backoff(&ctx); 2901 if (!ret) 2902 goto retry_conn_state; 2903 } 2904 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state); 2905 2906 crtc_state = drm_atomic_get_crtc_state(state, crtc); 2907 if (PTR_ERR(crtc_state) == -EDEADLK) { 2908 drm_atomic_state_clear(state); 2909 ret = drm_modeset_backoff(&ctx); 2910 if (!ret) 2911 goto retry_conn_state; 2912 } 2913 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 2914 2915 hdr_data.metadata_type = HDMI_STATIC_METADATA_TYPE1; 2916 hdr_data.hdmi_metadata_type1.eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR; 2917 hdr_data.hdmi_metadata_type1.metadata_type = HDMI_STATIC_METADATA_TYPE1; 2918 2919 hdr_blob = drm_property_create_blob(drm, sizeof(hdr_data), &hdr_data); 2920 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hdr_blob); 2921 2922 ret = drm_property_replace_blob_from_id(drm, 2923 &new_conn_state->hdr_output_metadata, 2924 hdr_blob->base.id, 2925 -1, sizeof(struct hdr_output_metadata), -1, 2926 &replaced); 2927 KUNIT_ASSERT_EQ(test, ret, 0); 2928 KUNIT_ASSERT_EQ(test, replaced, true); 2929 2930 crtc_state->mode_changed = true; 2931 2932 old_hdmi_update_failures = priv->hdmi_update_failures; 2933 2934 ret = drm_atomic_check_only(state); 2935 if (ret == -EDEADLK) { 2936 drm_atomic_state_clear(state); 2937 ret = drm_modeset_backoff(&ctx); 2938 if (!ret) 2939 goto retry_conn_state; 2940 } 2941 KUNIT_ASSERT_EQ(test, ret, 0); 2942 2943 ret = drm_atomic_commit(state); 2944 if (ret == -EDEADLK) { 2945 drm_atomic_state_clear(state); 2946 ret = drm_modeset_backoff(&ctx); 2947 if (!ret) 2948 goto retry_conn_state; 2949 } 2950 KUNIT_ASSERT_EQ(test, ret, 0); 2951 2952 KUNIT_EXPECT_LE(test, old_hdmi_update_failures, priv->hdmi_update_failures); 2953 2954 new_conn_state = conn->state; 2955 KUNIT_ASSERT_NOT_NULL(test, new_conn_state); 2956 2957 KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.output_bpc, 10); 2958 KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.infoframes.hdr_drm.set, true); 2959 2960 drm_modeset_drop_locks(&ctx); 2961 drm_modeset_acquire_fini(&ctx); 2962 } 2963 2964 static const struct drm_connector_hdmi_funcs reject_audio_infoframe_hdmi_funcs = { 2965 .avi = { 2966 .clear_infoframe = accept_infoframe_clear_infoframe, 2967 .write_infoframe = accept_infoframe_write_infoframe, 2968 }, 2969 .hdmi = { 2970 .clear_infoframe = accept_infoframe_clear_infoframe, 2971 .write_infoframe = accept_infoframe_write_infoframe, 2972 }, 2973 .audio = { 2974 .clear_infoframe = accept_infoframe_clear_infoframe, 2975 .write_infoframe = reject_infoframe_write_infoframe, 2976 }, 2977 }; 2978 2979 /* 2980 * Test that Audio InfoFrame is only programmed if we call a corresponding API, 2981 * thus the drivers can safely assume that they won't get Audio InfoFrames if 2982 * they don't call it. 2983 */ 2984 static void drm_test_check_reject_audio_infoframe(struct kunit *test) 2985 { 2986 struct drm_atomic_helper_connector_hdmi_priv *priv; 2987 struct drm_modeset_acquire_ctx ctx; 2988 struct drm_atomic_state *state; 2989 struct drm_crtc_state *crtc_state; 2990 struct drm_display_mode *preferred; 2991 struct drm_connector *conn; 2992 struct drm_device *drm; 2993 struct drm_crtc *crtc; 2994 int old_hdmi_update_failures; 2995 struct hdmi_audio_infoframe cea; 2996 int ret; 2997 2998 priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, 2999 BIT(HDMI_COLORSPACE_RGB), 3000 8, 3001 &reject_audio_infoframe_hdmi_funcs, 3002 test_edid_hdmi_1080p_rgb_max_200mhz); 3003 KUNIT_ASSERT_NOT_NULL(test, priv); 3004 3005 drm = &priv->drm; 3006 crtc = priv->crtc; 3007 conn = &priv->connector; 3008 3009 preferred = find_preferred_mode(conn); 3010 KUNIT_ASSERT_NOT_NULL(test, preferred); 3011 3012 drm_modeset_acquire_init(&ctx, 0); 3013 3014 retry_conn_enable: 3015 ret = drm_kunit_helper_enable_crtc_connector(test, drm, 3016 crtc, conn, 3017 preferred, 3018 &ctx); 3019 if (ret == -EDEADLK) { 3020 ret = drm_modeset_backoff(&ctx); 3021 if (!ret) 3022 goto retry_conn_enable; 3023 } 3024 KUNIT_ASSERT_EQ(test, ret, 0); 3025 3026 drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs); 3027 3028 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 3029 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 3030 3031 retry_crtc_state: 3032 crtc_state = drm_atomic_get_crtc_state(state, crtc); 3033 if (PTR_ERR(crtc_state) == -EDEADLK) { 3034 drm_atomic_state_clear(state); 3035 ret = drm_modeset_backoff(&ctx); 3036 if (!ret) 3037 goto retry_crtc_state; 3038 } 3039 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 3040 3041 crtc_state->mode_changed = true; 3042 3043 old_hdmi_update_failures = priv->hdmi_update_failures; 3044 3045 ret = drm_atomic_check_only(state); 3046 if (ret == -EDEADLK) { 3047 drm_atomic_state_clear(state); 3048 ret = drm_modeset_backoff(&ctx); 3049 if (!ret) 3050 goto retry_crtc_state; 3051 } 3052 KUNIT_ASSERT_EQ(test, ret, 0); 3053 3054 ret = drm_atomic_commit(state); 3055 if (ret == -EDEADLK) { 3056 drm_atomic_state_clear(state); 3057 ret = drm_modeset_backoff(&ctx); 3058 if (!ret) 3059 goto retry_crtc_state; 3060 } 3061 KUNIT_ASSERT_EQ(test, ret, 0); 3062 3063 KUNIT_EXPECT_EQ(test, old_hdmi_update_failures, priv->hdmi_update_failures); 3064 3065 /* 3066 * So, it works without Audio InfoFrame, let's fail with it in place, 3067 * checking that writing the infofraem actually gets triggered. 3068 */ 3069 3070 hdmi_audio_infoframe_init(&cea); 3071 cea.channels = 2; 3072 cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM; 3073 cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; 3074 cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; 3075 3076 ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(conn, &cea); 3077 KUNIT_ASSERT_EQ(test, ret, -EOPNOTSUPP); 3078 3079 state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx); 3080 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state); 3081 3082 retry_crtc_state_2: 3083 crtc_state = drm_atomic_get_crtc_state(state, crtc); 3084 if (PTR_ERR(crtc_state) == -EDEADLK) { 3085 drm_atomic_state_clear(state); 3086 ret = drm_modeset_backoff(&ctx); 3087 if (!ret) 3088 goto retry_crtc_state_2; 3089 } 3090 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state); 3091 3092 crtc_state->mode_changed = true; 3093 3094 old_hdmi_update_failures = priv->hdmi_update_failures; 3095 3096 ret = drm_atomic_check_only(state); 3097 if (ret == -EDEADLK) { 3098 drm_atomic_state_clear(state); 3099 ret = drm_modeset_backoff(&ctx); 3100 if (!ret) 3101 goto retry_crtc_state_2; 3102 } 3103 KUNIT_ASSERT_EQ(test, ret, 0); 3104 3105 ret = drm_atomic_commit(state); 3106 if (ret == -EDEADLK) { 3107 drm_atomic_state_clear(state); 3108 ret = drm_modeset_backoff(&ctx); 3109 if (!ret) 3110 goto retry_crtc_state_2; 3111 } 3112 KUNIT_ASSERT_EQ(test, ret, 0); 3113 3114 KUNIT_EXPECT_LE(test, old_hdmi_update_failures, priv->hdmi_update_failures); 3115 3116 drm_modeset_drop_locks(&ctx); 3117 drm_modeset_acquire_fini(&ctx); 3118 } 3119 3120 3121 static struct kunit_case drm_atomic_helper_connector_hdmi_infoframes_tests[] = { 3122 KUNIT_CASE(drm_test_check_infoframes), 3123 KUNIT_CASE(drm_test_check_reject_avi_infoframe), 3124 KUNIT_CASE(drm_test_check_reject_hdr_infoframe_bpc_8), 3125 KUNIT_CASE(drm_test_check_reject_hdr_infoframe_bpc_10), 3126 KUNIT_CASE(drm_test_check_reject_audio_infoframe), 3127 { } 3128 }; 3129 3130 static struct kunit_suite drm_atomic_helper_connector_hdmi_infoframes_test_suite = { 3131 .name = "drm_atomic_helper_connector_hdmi_infoframes", 3132 .test_cases = drm_atomic_helper_connector_hdmi_infoframes_tests, 3133 }; 3134 3135 kunit_test_suites( 3136 &drm_atomic_helper_connector_hdmi_check_test_suite, 3137 &drm_atomic_helper_connector_hdmi_reset_test_suite, 3138 &drm_atomic_helper_connector_hdmi_mode_valid_test_suite, 3139 &drm_atomic_helper_connector_hdmi_infoframes_test_suite, 3140 ); 3141 3142 MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>"); 3143 MODULE_DESCRIPTION("Kunit test for drm_hdmi_state_helper functions"); 3144 MODULE_LICENSE("GPL"); 3145