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