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