File Index
Files and directories
Sign in
FILE

drm_hdmi_state_helper_test.c

File preview with syntax highlighting.

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