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