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