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