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