xref: /linux/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c (revision b61104e7a6349bd2c2b3e2fb3260d87f15eda8f4)
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 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 
43 static struct drm_display_mode *find_preferred_mode(struct drm_connector *connector)
44 {
45 	struct drm_device *drm = connector->dev;
46 	struct drm_display_mode *mode, *preferred;
47 
48 	mutex_lock(&drm->mode_config.mutex);
49 	preferred = list_first_entry_or_null(&connector->modes, struct drm_display_mode, head);
50 	list_for_each_entry(mode, &connector->modes, head)
51 		if (mode->type & DRM_MODE_TYPE_PREFERRED)
52 			preferred = mode;
53 	mutex_unlock(&drm->mode_config.mutex);
54 
55 	return preferred;
56 }
57 
58 static int 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 
76 static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_funcs = {
77 };
78 
79 static enum drm_mode_status
80 reject_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 
87 static const struct drm_connector_hdmi_funcs reject_connector_hdmi_funcs = {
88 	.tmds_char_rate_valid	= reject_connector_tmds_char_rate_valid,
89 };
90 
91 static enum drm_mode_status
92 reject_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 
99 static 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 
103 static 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 
122 static 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 
128 static 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 
134 static 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 
141 static
142 struct 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 
214 static
215 struct drm_atomic_helper_connector_hdmi_priv *
216 drm_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  */
232 static 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 
260 retry_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  */
307 static 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 
335 retry_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  */
384 static 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 
412 retry_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  */
451 static 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 
479 retry_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  */
518 static 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 
546 retry_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  */
587 static 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 
615 retry_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  */
656 static 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 
684 retry_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  */
725 static 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 
753 retry_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  */
794 static 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 
827 retry_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 
840 retry_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 
873 static 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 
879 static void
880 check_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 
886 KUNIT_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  */
895 static 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 
924 retry_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  */
977 static 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 
1006 retry_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  */
1056 static 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 
1088 retry_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  */
1114 static 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 
1141 retry_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  */
1169 static 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 
1196 retry_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  */
1224 static 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 
1251 retry_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  */
1282 static 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 
1308 retry_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  */
1349 static 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 
1388 retry_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  */
1423 static 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 
1464 retry_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  */
1498 static 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 
1542 retry_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  */
1577 static 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 
1622 retry_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  */
1647 static 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 
1685 retry_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 
1702 retry_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  */
1733 static 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 
1778 retry_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  */
1804 static 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 
1851 retry_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  */
1877 static 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 
1926 retry_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  */
1953 static 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 
1992 retry_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  */
2019 static 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 
2060 retry_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. */
2083 static 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 
2110 retry_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 
2145 static 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 
2186 static 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  */
2195 static 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  */
2217 static 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  */
2241 static 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  */
2265 static 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  */
2287 static 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  */
2309 static 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 
2327 static 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 
2337 static 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  */
2347 static 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  */
2372 static 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  */
2401 static 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  */
2433 static 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 
2456 static 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 
2464 static 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 
2469 kunit_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 
2475 MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>");
2476 MODULE_DESCRIPTION("Kunit test for drm_hdmi_state_helper functions");
2477 MODULE_LICENSE("GPL");
2478