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