xref: /linux/drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c (revision ca220141fa8ebae09765a242076b2b77338106b0)
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 	int hdmi_update_failures;
40 };
41 
42 #define connector_to_priv(c) \
43 	container_of_const(c, struct drm_atomic_helper_connector_hdmi_priv, connector)
44 
45 #define encoder_to_priv(e) \
46 	container_of_const(e, struct drm_atomic_helper_connector_hdmi_priv, encoder)
47 
48 static struct drm_display_mode *find_preferred_mode(struct drm_connector *connector)
49 {
50 	struct drm_device *drm = connector->dev;
51 	struct drm_display_mode *mode, *preferred;
52 
53 	mutex_lock(&drm->mode_config.mutex);
54 	preferred = list_first_entry_or_null(&connector->modes, struct drm_display_mode, head);
55 	list_for_each_entry(mode, &connector->modes, head)
56 		if (mode->type & DRM_MODE_TYPE_PREFERRED)
57 			preferred = mode;
58 	mutex_unlock(&drm->mode_config.mutex);
59 
60 	return preferred;
61 }
62 
63 static int set_connector_edid(struct kunit *test, struct drm_connector *connector,
64 			      const void *edid, size_t edid_len)
65 {
66 	struct drm_atomic_helper_connector_hdmi_priv *priv =
67 		connector_to_priv(connector);
68 	struct drm_device *drm = connector->dev;
69 	int ret;
70 
71 	priv->current_edid = edid;
72 	priv->current_edid_len = edid_len;
73 
74 	mutex_lock(&drm->mode_config.mutex);
75 	ret = connector->funcs->fill_modes(connector, 4096, 4096);
76 	mutex_unlock(&drm->mode_config.mutex);
77 
78 	return ret;
79 }
80 
81 static int accept_infoframe_clear_infoframe(struct drm_connector *connector)
82 {
83 	return 0;
84 }
85 
86 static int accept_infoframe_write_infoframe(struct drm_connector *connector,
87 					    const u8 *buffer, size_t len)
88 {
89 	return 0;
90 }
91 
92 static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_funcs = {
93 	.avi = {
94 		.clear_infoframe = accept_infoframe_clear_infoframe,
95 		.write_infoframe = accept_infoframe_write_infoframe,
96 	},
97 	.hdmi = {
98 		.clear_infoframe = accept_infoframe_clear_infoframe,
99 		.write_infoframe = accept_infoframe_write_infoframe,
100 	},
101 };
102 
103 static enum drm_mode_status
104 reject_connector_tmds_char_rate_valid(const struct drm_connector *connector,
105 				      const struct drm_display_mode *mode,
106 				      unsigned long long tmds_rate)
107 {
108 	return MODE_BAD;
109 }
110 
111 static const struct drm_connector_hdmi_funcs reject_connector_hdmi_funcs = {
112 	.tmds_char_rate_valid	= reject_connector_tmds_char_rate_valid,
113 	.avi = {
114 		.clear_infoframe = accept_infoframe_clear_infoframe,
115 		.write_infoframe = accept_infoframe_write_infoframe,
116 	},
117 	.hdmi = {
118 		.clear_infoframe = accept_infoframe_clear_infoframe,
119 		.write_infoframe = accept_infoframe_write_infoframe,
120 	},
121 };
122 
123 static enum drm_mode_status
124 reject_100mhz_connector_tmds_char_rate_valid(const struct drm_connector *connector,
125 					     const struct drm_display_mode *mode,
126 					     unsigned long long tmds_rate)
127 {
128 	return (tmds_rate > 100ULL * 1000 * 1000) ? MODE_BAD : MODE_OK;
129 }
130 
131 static const struct drm_connector_hdmi_funcs reject_100mhz_connector_hdmi_funcs = {
132 	.tmds_char_rate_valid	= reject_100mhz_connector_tmds_char_rate_valid,
133 	.avi = {
134 		.clear_infoframe = accept_infoframe_clear_infoframe,
135 		.write_infoframe = accept_infoframe_write_infoframe,
136 	},
137 	.hdmi = {
138 		.clear_infoframe = accept_infoframe_clear_infoframe,
139 		.write_infoframe = accept_infoframe_write_infoframe,
140 	},
141 };
142 
143 static int dummy_connector_get_modes(struct drm_connector *connector)
144 {
145 	struct drm_atomic_helper_connector_hdmi_priv *priv =
146 		connector_to_priv(connector);
147 	const struct drm_edid *edid;
148 	unsigned int num_modes;
149 
150 	edid = drm_edid_alloc(priv->current_edid, priv->current_edid_len);
151 	if (!edid)
152 		return -EINVAL;
153 
154 	drm_edid_connector_update(connector, edid);
155 	num_modes = drm_edid_connector_add_modes(connector);
156 
157 	drm_edid_free(edid);
158 
159 	return num_modes;
160 }
161 
162 static const struct drm_connector_helper_funcs dummy_connector_helper_funcs = {
163 	.atomic_check	= drm_atomic_helper_connector_hdmi_check,
164 	.get_modes	= dummy_connector_get_modes,
165 	.mode_valid	= drm_hdmi_connector_mode_valid,
166 };
167 
168 static void dummy_hdmi_connector_reset(struct drm_connector *connector)
169 {
170 	drm_atomic_helper_connector_reset(connector);
171 	__drm_atomic_helper_connector_hdmi_reset(connector, connector->state);
172 }
173 
174 static const struct drm_connector_funcs dummy_connector_funcs = {
175 	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
176 	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
177 	.fill_modes		= drm_helper_probe_single_connector_modes,
178 	.reset			= dummy_hdmi_connector_reset,
179 };
180 
181 static void test_encoder_atomic_enable(struct drm_encoder *encoder,
182 			      struct drm_atomic_state *state)
183 {
184 	struct drm_atomic_helper_connector_hdmi_priv *priv =
185 		encoder_to_priv(encoder);
186 	int ret;
187 
188 	ret = drm_atomic_helper_connector_hdmi_update_infoframes(&priv->connector, state);
189 	if (ret)
190 		priv->hdmi_update_failures++;
191 }
192 
193 static const struct drm_encoder_helper_funcs test_encoder_helper_funcs = {
194 	.atomic_enable = test_encoder_atomic_enable,
195 };
196 
197 static
198 struct drm_atomic_helper_connector_hdmi_priv *
199 __connector_hdmi_init(struct kunit *test,
200 		      unsigned int formats,
201 		      unsigned int max_bpc,
202 		      const struct drm_connector_hdmi_funcs *hdmi_funcs,
203 		      const void *edid_data, size_t edid_len)
204 {
205 	struct drm_atomic_helper_connector_hdmi_priv *priv;
206 	struct drm_connector *conn;
207 	struct drm_encoder *enc;
208 	struct drm_device *drm;
209 	struct device *dev;
210 	int ret;
211 
212 	dev = drm_kunit_helper_alloc_device(test);
213 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
214 
215 	priv = drm_kunit_helper_alloc_drm_device(test, dev,
216 						 struct drm_atomic_helper_connector_hdmi_priv, drm,
217 						 DRIVER_MODESET | DRIVER_ATOMIC);
218 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
219 	test->priv = priv;
220 
221 	drm = &priv->drm;
222 	priv->plane = drm_kunit_helper_create_primary_plane(test, drm,
223 							    NULL,
224 							    NULL,
225 							    NULL, 0,
226 							    NULL);
227 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->plane);
228 
229 	priv->crtc = drm_kunit_helper_create_crtc(test, drm,
230 						  priv->plane, NULL,
231 						  NULL,
232 						  NULL);
233 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->crtc);
234 
235 	enc = &priv->encoder;
236 	ret = drmm_encoder_init(drm, enc, NULL, DRM_MODE_ENCODER_TMDS, NULL);
237 	KUNIT_ASSERT_EQ(test, ret, 0);
238 
239 	enc->possible_crtcs = drm_crtc_mask(priv->crtc);
240 
241 	conn = &priv->connector;
242 	conn->ycbcr_420_allowed = !!(formats & BIT(HDMI_COLORSPACE_YUV420));
243 
244 	ret = drmm_connector_hdmi_init(drm, conn,
245 				       "Vendor", "Product",
246 				       &dummy_connector_funcs,
247 				       hdmi_funcs,
248 				       DRM_MODE_CONNECTOR_HDMIA,
249 				       NULL,
250 				       formats,
251 				       max_bpc);
252 	KUNIT_ASSERT_EQ(test, ret, 0);
253 
254 	drm_connector_helper_add(conn, &dummy_connector_helper_funcs);
255 	drm_connector_attach_encoder(conn, enc);
256 
257 	drm_mode_config_reset(drm);
258 
259 	if (edid_data && edid_len) {
260 		ret = set_connector_edid(test, &priv->connector, edid_data, edid_len);
261 		KUNIT_ASSERT_GT(test, ret, 0);
262 	}
263 
264 	return priv;
265 }
266 
267 #define drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test, formats, max_bpc, funcs, edid) \
268 	__connector_hdmi_init(test, formats, max_bpc, funcs, edid, ARRAY_SIZE(edid))
269 
270 static
271 struct drm_atomic_helper_connector_hdmi_priv *
272 drm_kunit_helper_connector_hdmi_init(struct kunit *test,
273 				     unsigned int formats,
274 				     unsigned int max_bpc)
275 {
276 	return drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
277 				formats,
278 				max_bpc,
279 				&dummy_connector_hdmi_funcs,
280 				test_edid_hdmi_1080p_rgb_max_200mhz);
281 }
282 
283 /*
284  * Test that if we change the RGB quantization property to a different
285  * value, we trigger a mode change on the connector's CRTC, which will
286  * in turn disable/enable the connector.
287  */
288 static void drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit *test)
289 {
290 	struct drm_atomic_helper_connector_hdmi_priv *priv;
291 	struct drm_modeset_acquire_ctx ctx;
292 	struct drm_connector_state *old_conn_state;
293 	struct drm_connector_state *new_conn_state;
294 	struct drm_crtc_state *crtc_state;
295 	struct drm_atomic_state *state;
296 	struct drm_display_mode *preferred;
297 	struct drm_connector *conn;
298 	struct drm_device *drm;
299 	struct drm_crtc *crtc;
300 	int ret;
301 
302 	priv = drm_kunit_helper_connector_hdmi_init(test,
303 						    BIT(HDMI_COLORSPACE_RGB),
304 						    8);
305 	KUNIT_ASSERT_NOT_NULL(test, priv);
306 
307 	drm = &priv->drm;
308 	crtc = priv->crtc;
309 	conn = &priv->connector;
310 
311 	preferred = find_preferred_mode(conn);
312 	KUNIT_ASSERT_NOT_NULL(test, preferred);
313 
314 	drm_modeset_acquire_init(&ctx, 0);
315 
316 retry_conn_enable:
317 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
318 						     crtc, conn,
319 						     preferred,
320 						     &ctx);
321 	if (ret == -EDEADLK) {
322 		ret = drm_modeset_backoff(&ctx);
323 		if (!ret)
324 			goto retry_conn_enable;
325 	}
326 	KUNIT_ASSERT_EQ(test, ret, 0);
327 
328 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
329 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
330 
331 	new_conn_state = drm_atomic_get_connector_state(state, conn);
332 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
333 
334 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
335 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
336 
337 	new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
338 
339 	KUNIT_ASSERT_NE(test,
340 			old_conn_state->hdmi.broadcast_rgb,
341 			new_conn_state->hdmi.broadcast_rgb);
342 
343 	ret = drm_atomic_check_only(state);
344 	KUNIT_ASSERT_EQ(test, ret, 0);
345 
346 	new_conn_state = drm_atomic_get_new_connector_state(state, conn);
347 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
348 	KUNIT_EXPECT_EQ(test, new_conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_FULL);
349 
350 	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
351 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
352 	KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed);
353 
354 	drm_modeset_drop_locks(&ctx);
355 	drm_modeset_acquire_fini(&ctx);
356 }
357 
358 /*
359  * Test that if we set the RGB quantization property to the same value,
360  * we don't trigger a mode change on the connector's CRTC and leave the
361  * connector unaffected.
362  */
363 static void drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *test)
364 {
365 	struct drm_atomic_helper_connector_hdmi_priv *priv;
366 	struct drm_modeset_acquire_ctx ctx;
367 	struct drm_connector_state *old_conn_state;
368 	struct drm_connector_state *new_conn_state;
369 	struct drm_crtc_state *crtc_state;
370 	struct drm_atomic_state *state;
371 	struct drm_display_mode *preferred;
372 	struct drm_connector *conn;
373 	struct drm_device *drm;
374 	struct drm_crtc *crtc;
375 	int ret;
376 
377 	priv = drm_kunit_helper_connector_hdmi_init(test,
378 						    BIT(HDMI_COLORSPACE_RGB),
379 						    8);
380 	KUNIT_ASSERT_NOT_NULL(test, priv);
381 
382 	drm = &priv->drm;
383 	crtc = priv->crtc;
384 	conn = &priv->connector;
385 
386 	preferred = find_preferred_mode(conn);
387 	KUNIT_ASSERT_NOT_NULL(test, preferred);
388 
389 	drm_modeset_acquire_init(&ctx, 0);
390 
391 retry_conn_enable:
392 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
393 						     crtc, conn,
394 						     preferred,
395 						     &ctx);
396 	if (ret == -EDEADLK) {
397 		ret = drm_modeset_backoff(&ctx);
398 		if (!ret)
399 			goto retry_conn_enable;
400 	}
401 	KUNIT_ASSERT_EQ(test, ret, 0);
402 
403 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
404 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
405 
406 	new_conn_state = drm_atomic_get_connector_state(state, conn);
407 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
408 
409 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
410 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
411 
412 	new_conn_state->hdmi.broadcast_rgb = old_conn_state->hdmi.broadcast_rgb;
413 
414 	ret = drm_atomic_check_only(state);
415 	KUNIT_ASSERT_EQ(test, ret, 0);
416 
417 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
418 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
419 
420 	new_conn_state = drm_atomic_get_new_connector_state(state, conn);
421 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
422 
423 	KUNIT_EXPECT_EQ(test,
424 			old_conn_state->hdmi.broadcast_rgb,
425 			new_conn_state->hdmi.broadcast_rgb);
426 
427 	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
428 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
429 	KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed);
430 
431 	drm_modeset_drop_locks(&ctx);
432 	drm_modeset_acquire_fini(&ctx);
433 }
434 
435 /*
436  * Test that for an HDMI connector, with an HDMI monitor, if the
437  * Broadcast RGB property is set to auto with a mode that isn't the
438  * VIC-1 mode, we will get a limited RGB Quantization Range.
439  */
440 static void drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit *test)
441 {
442 	struct drm_atomic_helper_connector_hdmi_priv *priv;
443 	struct drm_modeset_acquire_ctx ctx;
444 	struct drm_connector_state *conn_state;
445 	struct drm_atomic_state *state;
446 	struct drm_display_mode *preferred;
447 	struct drm_connector *conn;
448 	struct drm_device *drm;
449 	struct drm_crtc *crtc;
450 	int ret;
451 
452 	priv = drm_kunit_helper_connector_hdmi_init(test,
453 						    BIT(HDMI_COLORSPACE_RGB),
454 						    8);
455 	KUNIT_ASSERT_NOT_NULL(test, priv);
456 
457 	drm = &priv->drm;
458 	crtc = priv->crtc;
459 	conn = &priv->connector;
460 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
461 
462 	preferred = find_preferred_mode(conn);
463 	KUNIT_ASSERT_NOT_NULL(test, preferred);
464 	KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
465 
466 	drm_modeset_acquire_init(&ctx, 0);
467 
468 retry_conn_enable:
469 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
470 						     crtc, conn,
471 						     preferred,
472 						     &ctx);
473 	if (ret == -EDEADLK) {
474 		ret = drm_modeset_backoff(&ctx);
475 		if (!ret)
476 			goto retry_conn_enable;
477 	}
478 	KUNIT_ASSERT_EQ(test, ret, 0);
479 
480 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
481 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
482 
483 	conn_state = drm_atomic_get_connector_state(state, conn);
484 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
485 
486 	KUNIT_ASSERT_EQ(test,
487 			conn_state->hdmi.broadcast_rgb,
488 			DRM_HDMI_BROADCAST_RGB_AUTO);
489 
490 	ret = drm_atomic_check_only(state);
491 	KUNIT_ASSERT_EQ(test, ret, 0);
492 
493 	conn_state = drm_atomic_get_new_connector_state(state, conn);
494 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
495 
496 	KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
497 
498 	drm_modeset_drop_locks(&ctx);
499 	drm_modeset_acquire_fini(&ctx);
500 }
501 
502 /*
503  * Test that for an HDMI connector, with an HDMI monitor, if the
504  * Broadcast RGB property is set to auto with a VIC-1 mode, we will get
505  * a full RGB Quantization Range.
506  */
507 static void drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit *test)
508 {
509 	struct drm_atomic_helper_connector_hdmi_priv *priv;
510 	struct drm_modeset_acquire_ctx ctx;
511 	struct drm_connector_state *conn_state;
512 	struct drm_atomic_state *state;
513 	struct drm_display_mode *mode;
514 	struct drm_connector *conn;
515 	struct drm_device *drm;
516 	struct drm_crtc *crtc;
517 	int ret;
518 
519 	priv = drm_kunit_helper_connector_hdmi_init(test,
520 						    BIT(HDMI_COLORSPACE_RGB),
521 						    8);
522 	KUNIT_ASSERT_NOT_NULL(test, priv);
523 
524 	drm = &priv->drm;
525 	conn = &priv->connector;
526 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
527 
528 	drm_modeset_acquire_init(&ctx, 0);
529 
530 	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
531 	KUNIT_ASSERT_NOT_NULL(test, mode);
532 
533 	crtc = priv->crtc;
534 
535 retry_conn_enable:
536 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
537 						     crtc, conn,
538 						     mode,
539 						     &ctx);
540 	if (ret == -EDEADLK) {
541 		ret = drm_modeset_backoff(&ctx);
542 		if (!ret)
543 			goto retry_conn_enable;
544 	}
545 	KUNIT_ASSERT_EQ(test, ret, 0);
546 
547 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
548 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
549 
550 	conn_state = drm_atomic_get_connector_state(state, conn);
551 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
552 
553 	KUNIT_ASSERT_EQ(test,
554 			conn_state->hdmi.broadcast_rgb,
555 			DRM_HDMI_BROADCAST_RGB_AUTO);
556 
557 	ret = drm_atomic_check_only(state);
558 	KUNIT_ASSERT_EQ(test, ret, 0);
559 
560 	conn_state = drm_atomic_get_new_connector_state(state, conn);
561 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
562 
563 	KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range);
564 
565 	drm_modeset_drop_locks(&ctx);
566 	drm_modeset_acquire_fini(&ctx);
567 }
568 
569 /*
570  * Test that for an HDMI connector, with an HDMI monitor, if the
571  * Broadcast RGB property is set to full with a mode that isn't the
572  * VIC-1 mode, we will get a full RGB Quantization Range.
573  */
574 static void drm_test_check_broadcast_rgb_full_cea_mode(struct kunit *test)
575 {
576 	struct drm_atomic_helper_connector_hdmi_priv *priv;
577 	struct drm_modeset_acquire_ctx ctx;
578 	struct drm_connector_state *conn_state;
579 	struct drm_atomic_state *state;
580 	struct drm_display_mode *preferred;
581 	struct drm_connector *conn;
582 	struct drm_device *drm;
583 	struct drm_crtc *crtc;
584 	int ret;
585 
586 	priv = drm_kunit_helper_connector_hdmi_init(test,
587 						    BIT(HDMI_COLORSPACE_RGB),
588 						    8);
589 	KUNIT_ASSERT_NOT_NULL(test, priv);
590 
591 	drm = &priv->drm;
592 	crtc = priv->crtc;
593 	conn = &priv->connector;
594 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
595 
596 	preferred = find_preferred_mode(conn);
597 	KUNIT_ASSERT_NOT_NULL(test, preferred);
598 	KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
599 
600 	drm_modeset_acquire_init(&ctx, 0);
601 
602 retry_conn_enable:
603 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
604 						     crtc, conn,
605 						     preferred,
606 						     &ctx);
607 	if (ret == -EDEADLK) {
608 		ret = drm_modeset_backoff(&ctx);
609 		if (!ret)
610 			goto retry_conn_enable;
611 	}
612 	KUNIT_ASSERT_EQ(test, ret, 0);
613 
614 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
615 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
616 
617 	conn_state = drm_atomic_get_connector_state(state, conn);
618 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
619 
620 	conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
621 
622 	ret = drm_atomic_check_only(state);
623 	KUNIT_ASSERT_EQ(test, ret, 0);
624 
625 	conn_state = drm_atomic_get_new_connector_state(state, conn);
626 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
627 
628 	KUNIT_ASSERT_EQ(test,
629 			conn_state->hdmi.broadcast_rgb,
630 			DRM_HDMI_BROADCAST_RGB_FULL);
631 
632 	KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range);
633 
634 	drm_modeset_drop_locks(&ctx);
635 	drm_modeset_acquire_fini(&ctx);
636 }
637 
638 /*
639  * Test that for an HDMI connector, with an HDMI monitor, if the
640  * Broadcast RGB property is set to full with a VIC-1 mode, we will get
641  * a full RGB Quantization Range.
642  */
643 static void drm_test_check_broadcast_rgb_full_cea_mode_vic_1(struct kunit *test)
644 {
645 	struct drm_atomic_helper_connector_hdmi_priv *priv;
646 	struct drm_modeset_acquire_ctx ctx;
647 	struct drm_connector_state *conn_state;
648 	struct drm_atomic_state *state;
649 	struct drm_display_mode *mode;
650 	struct drm_connector *conn;
651 	struct drm_device *drm;
652 	struct drm_crtc *crtc;
653 	int ret;
654 
655 	priv = drm_kunit_helper_connector_hdmi_init(test,
656 						    BIT(HDMI_COLORSPACE_RGB),
657 						    8);
658 	KUNIT_ASSERT_NOT_NULL(test, priv);
659 
660 	drm = &priv->drm;
661 	conn = &priv->connector;
662 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
663 
664 	drm_modeset_acquire_init(&ctx, 0);
665 
666 	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
667 	KUNIT_ASSERT_NOT_NULL(test, mode);
668 
669 	crtc = priv->crtc;
670 
671 retry_conn_enable:
672 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
673 						     crtc, conn,
674 						     mode,
675 						     &ctx);
676 	if (ret == -EDEADLK) {
677 		ret = drm_modeset_backoff(&ctx);
678 		if (!ret)
679 			goto retry_conn_enable;
680 	}
681 	KUNIT_ASSERT_EQ(test, ret, 0);
682 
683 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
684 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
685 
686 	conn_state = drm_atomic_get_connector_state(state, conn);
687 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
688 
689 	conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
690 
691 	ret = drm_atomic_check_only(state);
692 	KUNIT_ASSERT_EQ(test, ret, 0);
693 
694 	conn_state = drm_atomic_get_new_connector_state(state, conn);
695 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
696 
697 	KUNIT_ASSERT_EQ(test,
698 			conn_state->hdmi.broadcast_rgb,
699 			DRM_HDMI_BROADCAST_RGB_FULL);
700 
701 	KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range);
702 
703 	drm_modeset_drop_locks(&ctx);
704 	drm_modeset_acquire_fini(&ctx);
705 }
706 
707 /*
708  * Test that for an HDMI connector, with an HDMI monitor, if the
709  * Broadcast RGB property is set to limited with a mode that isn't the
710  * VIC-1 mode, we will get a limited RGB Quantization Range.
711  */
712 static void drm_test_check_broadcast_rgb_limited_cea_mode(struct kunit *test)
713 {
714 	struct drm_atomic_helper_connector_hdmi_priv *priv;
715 	struct drm_modeset_acquire_ctx ctx;
716 	struct drm_connector_state *conn_state;
717 	struct drm_atomic_state *state;
718 	struct drm_display_mode *preferred;
719 	struct drm_connector *conn;
720 	struct drm_device *drm;
721 	struct drm_crtc *crtc;
722 	int ret;
723 
724 	priv = drm_kunit_helper_connector_hdmi_init(test,
725 						    BIT(HDMI_COLORSPACE_RGB),
726 						    8);
727 	KUNIT_ASSERT_NOT_NULL(test, priv);
728 
729 	drm = &priv->drm;
730 	crtc = priv->crtc;
731 	conn = &priv->connector;
732 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
733 
734 	preferred = find_preferred_mode(conn);
735 	KUNIT_ASSERT_NOT_NULL(test, preferred);
736 	KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
737 
738 	drm_modeset_acquire_init(&ctx, 0);
739 
740 retry_conn_enable:
741 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
742 						     crtc, conn,
743 						     preferred,
744 						     &ctx);
745 	if (ret == -EDEADLK) {
746 		ret = drm_modeset_backoff(&ctx);
747 		if (!ret)
748 			goto retry_conn_enable;
749 	}
750 	KUNIT_ASSERT_EQ(test, ret, 0);
751 
752 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
753 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
754 
755 	conn_state = drm_atomic_get_connector_state(state, conn);
756 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
757 
758 	conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED;
759 
760 	ret = drm_atomic_check_only(state);
761 	KUNIT_ASSERT_EQ(test, ret, 0);
762 
763 	conn_state = drm_atomic_get_new_connector_state(state, conn);
764 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
765 
766 	KUNIT_ASSERT_EQ(test,
767 			conn_state->hdmi.broadcast_rgb,
768 			DRM_HDMI_BROADCAST_RGB_LIMITED);
769 
770 	KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
771 
772 	drm_modeset_drop_locks(&ctx);
773 	drm_modeset_acquire_fini(&ctx);
774 }
775 
776 /*
777  * Test that for an HDMI connector, with an HDMI monitor, if the
778  * Broadcast RGB property is set to limited with a VIC-1 mode, we will
779  * get a limited RGB Quantization Range.
780  */
781 static void drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit *test)
782 {
783 	struct drm_atomic_helper_connector_hdmi_priv *priv;
784 	struct drm_modeset_acquire_ctx ctx;
785 	struct drm_connector_state *conn_state;
786 	struct drm_atomic_state *state;
787 	struct drm_display_mode *mode;
788 	struct drm_connector *conn;
789 	struct drm_device *drm;
790 	struct drm_crtc *crtc;
791 	int ret;
792 
793 	priv = drm_kunit_helper_connector_hdmi_init(test,
794 						    BIT(HDMI_COLORSPACE_RGB),
795 						    8);
796 	KUNIT_ASSERT_NOT_NULL(test, priv);
797 
798 	drm = &priv->drm;
799 	conn = &priv->connector;
800 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
801 
802 	drm_modeset_acquire_init(&ctx, 0);
803 
804 	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
805 	KUNIT_ASSERT_NOT_NULL(test, mode);
806 
807 	crtc = priv->crtc;
808 
809 retry_conn_enable:
810 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
811 						     crtc, conn,
812 						     mode,
813 						     &ctx);
814 	if (ret == -EDEADLK) {
815 		ret = drm_modeset_backoff(&ctx);
816 		if (!ret)
817 			goto retry_conn_enable;
818 	}
819 	KUNIT_ASSERT_EQ(test, ret, 0);
820 
821 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
822 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
823 
824 	conn_state = drm_atomic_get_connector_state(state, conn);
825 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
826 
827 	conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED;
828 
829 	ret = drm_atomic_check_only(state);
830 	KUNIT_ASSERT_EQ(test, ret, 0);
831 
832 	conn_state = drm_atomic_get_new_connector_state(state, conn);
833 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
834 
835 	KUNIT_ASSERT_EQ(test,
836 			conn_state->hdmi.broadcast_rgb,
837 			DRM_HDMI_BROADCAST_RGB_LIMITED);
838 
839 	KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
840 
841 	drm_modeset_drop_locks(&ctx);
842 	drm_modeset_acquire_fini(&ctx);
843 }
844 
845 /*
846  * Test that for an HDMI connector, with an HDMI monitor, we will
847  * get a limited RGB Quantization Range with a YUV420 mode, no
848  * matter what the value of the Broadcast RGB property is set to.
849  */
850 static void drm_test_check_broadcast_rgb_cea_mode_yuv420(struct kunit *test)
851 {
852 	struct drm_atomic_helper_connector_hdmi_priv *priv;
853 	enum drm_hdmi_broadcast_rgb broadcast_rgb;
854 	struct drm_modeset_acquire_ctx ctx;
855 	struct drm_connector_state *conn_state;
856 	struct drm_atomic_state *state;
857 	struct drm_display_mode *mode;
858 	struct drm_connector *conn;
859 	struct drm_device *drm;
860 	struct drm_crtc *crtc;
861 	int ret;
862 
863 	broadcast_rgb = *(enum drm_hdmi_broadcast_rgb *)test->param_value;
864 
865 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
866 				BIT(HDMI_COLORSPACE_RGB) |
867 				BIT(HDMI_COLORSPACE_YUV420),
868 				8,
869 				&dummy_connector_hdmi_funcs,
870 				test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz);
871 	KUNIT_ASSERT_NOT_NULL(test, priv);
872 
873 	drm = &priv->drm;
874 	crtc = priv->crtc;
875 	conn = &priv->connector;
876 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
877 
878 	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95);
879 	KUNIT_ASSERT_NOT_NULL(test, mode);
880 
881 	drm_modeset_acquire_init(&ctx, 0);
882 
883 retry_conn_enable:
884 	ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn,
885 						     mode, &ctx);
886 	if (ret == -EDEADLK) {
887 		ret = drm_modeset_backoff(&ctx);
888 		if (!ret)
889 			goto retry_conn_enable;
890 	}
891 	KUNIT_ASSERT_EQ(test, ret, 0);
892 
893 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
894 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
895 
896 retry_conn_state:
897 	conn_state = drm_atomic_get_connector_state(state, conn);
898 	if (PTR_ERR(conn_state) == -EDEADLK) {
899 		drm_atomic_state_clear(state);
900 		ret = drm_modeset_backoff(&ctx);
901 		if (!ret)
902 			goto retry_conn_state;
903 	}
904 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
905 
906 	conn_state->hdmi.broadcast_rgb = broadcast_rgb;
907 
908 	ret = drm_atomic_check_only(state);
909 	if (ret == -EDEADLK) {
910 		drm_atomic_state_clear(state);
911 		ret = drm_modeset_backoff(&ctx);
912 		if (!ret)
913 			goto retry_conn_state;
914 	}
915 	KUNIT_ASSERT_EQ(test, ret, 0);
916 
917 	conn_state = drm_atomic_get_new_connector_state(state, conn);
918 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
919 
920 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.broadcast_rgb, broadcast_rgb);
921 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420);
922 
923 	KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
924 
925 	drm_modeset_drop_locks(&ctx);
926 	drm_modeset_acquire_fini(&ctx);
927 }
928 
929 static const enum drm_hdmi_broadcast_rgb check_broadcast_rgb_cea_mode_yuv420_tests[] = {
930 	DRM_HDMI_BROADCAST_RGB_AUTO,
931 	DRM_HDMI_BROADCAST_RGB_FULL,
932 	DRM_HDMI_BROADCAST_RGB_LIMITED,
933 };
934 
935 static void
936 check_broadcast_rgb_cea_mode_yuv420_desc(const enum drm_hdmi_broadcast_rgb *broadcast_rgb,
937 					 char *desc)
938 {
939 	sprintf(desc, "%s", drm_hdmi_connector_get_broadcast_rgb_name(*broadcast_rgb));
940 }
941 
942 KUNIT_ARRAY_PARAM(check_broadcast_rgb_cea_mode_yuv420,
943 		  check_broadcast_rgb_cea_mode_yuv420_tests,
944 		  check_broadcast_rgb_cea_mode_yuv420_desc);
945 
946 /*
947  * Test that if we change the maximum bpc property to a different value,
948  * we trigger a mode change on the connector's CRTC, which will in turn
949  * disable/enable the connector.
950  */
951 static void drm_test_check_output_bpc_crtc_mode_changed(struct kunit *test)
952 {
953 	struct drm_atomic_helper_connector_hdmi_priv *priv;
954 	struct drm_modeset_acquire_ctx ctx;
955 	struct drm_connector_state *old_conn_state;
956 	struct drm_connector_state *new_conn_state;
957 	struct drm_crtc_state *crtc_state;
958 	struct drm_atomic_state *state;
959 	struct drm_display_mode *preferred;
960 	struct drm_connector *conn;
961 	struct drm_device *drm;
962 	struct drm_crtc *crtc;
963 	int ret;
964 
965 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
966 				BIT(HDMI_COLORSPACE_RGB),
967 				10,
968 				&dummy_connector_hdmi_funcs,
969 				test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz);
970 	KUNIT_ASSERT_NOT_NULL(test, priv);
971 
972 	drm = &priv->drm;
973 	crtc = priv->crtc;
974 	conn = &priv->connector;
975 	preferred = find_preferred_mode(conn);
976 	KUNIT_ASSERT_NOT_NULL(test, preferred);
977 
978 	drm_modeset_acquire_init(&ctx, 0);
979 
980 retry_conn_enable:
981 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
982 						     crtc, conn,
983 						     preferred,
984 						     &ctx);
985 	if (ret == -EDEADLK) {
986 		ret = drm_modeset_backoff(&ctx);
987 		if (!ret)
988 			goto retry_conn_enable;
989 	}
990 	KUNIT_ASSERT_EQ(test, ret, 0);
991 
992 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
993 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
994 
995 	new_conn_state = drm_atomic_get_connector_state(state, conn);
996 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
997 
998 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
999 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
1000 
1001 	new_conn_state->max_requested_bpc = 8;
1002 
1003 	KUNIT_ASSERT_NE(test,
1004 			old_conn_state->max_requested_bpc,
1005 			new_conn_state->max_requested_bpc);
1006 
1007 	ret = drm_atomic_check_only(state);
1008 	KUNIT_ASSERT_EQ(test, ret, 0);
1009 
1010 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
1011 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
1012 
1013 	new_conn_state = drm_atomic_get_new_connector_state(state, conn);
1014 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
1015 
1016 	KUNIT_ASSERT_NE(test,
1017 			old_conn_state->hdmi.output_bpc,
1018 			new_conn_state->hdmi.output_bpc);
1019 
1020 	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1021 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1022 	KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed);
1023 
1024 	drm_modeset_drop_locks(&ctx);
1025 	drm_modeset_acquire_fini(&ctx);
1026 }
1027 
1028 /*
1029  * Test that if we set the output bpc property to the same value, we
1030  * don't trigger a mode change on the connector's CRTC and leave the
1031  * connector unaffected.
1032  */
1033 static void drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test)
1034 {
1035 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1036 	struct drm_modeset_acquire_ctx ctx;
1037 	struct drm_connector_state *old_conn_state;
1038 	struct drm_connector_state *new_conn_state;
1039 	struct drm_crtc_state *crtc_state;
1040 	struct drm_atomic_state *state;
1041 	struct drm_display_mode *preferred;
1042 	struct drm_connector *conn;
1043 	struct drm_device *drm;
1044 	struct drm_crtc *crtc;
1045 	int ret;
1046 
1047 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1048 				BIT(HDMI_COLORSPACE_RGB),
1049 				10,
1050 				&dummy_connector_hdmi_funcs,
1051 				test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz);
1052 	KUNIT_ASSERT_NOT_NULL(test, priv);
1053 
1054 	drm = &priv->drm;
1055 	crtc = priv->crtc;
1056 	conn = &priv->connector;
1057 	preferred = find_preferred_mode(conn);
1058 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1059 
1060 	drm_modeset_acquire_init(&ctx, 0);
1061 
1062 retry_conn_enable:
1063 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
1064 						     crtc, conn,
1065 						     preferred,
1066 						     &ctx);
1067 	if (ret == -EDEADLK) {
1068 		ret = drm_modeset_backoff(&ctx);
1069 		if (!ret)
1070 			goto retry_conn_enable;
1071 	}
1072 	KUNIT_ASSERT_EQ(test, ret, 0);
1073 
1074 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
1075 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1076 
1077 	new_conn_state = drm_atomic_get_connector_state(state, conn);
1078 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
1079 
1080 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
1081 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
1082 
1083 	KUNIT_ASSERT_EQ(test,
1084 			new_conn_state->hdmi.output_bpc,
1085 			old_conn_state->hdmi.output_bpc);
1086 
1087 	ret = drm_atomic_check_only(state);
1088 	KUNIT_ASSERT_EQ(test, ret, 0);
1089 
1090 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
1091 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
1092 
1093 	new_conn_state = drm_atomic_get_new_connector_state(state, conn);
1094 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
1095 
1096 	KUNIT_EXPECT_EQ(test,
1097 			old_conn_state->hdmi.output_bpc,
1098 			new_conn_state->hdmi.output_bpc);
1099 
1100 	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
1101 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1102 	KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed);
1103 
1104 	drm_modeset_drop_locks(&ctx);
1105 	drm_modeset_acquire_fini(&ctx);
1106 }
1107 
1108 /*
1109  * Test that if we have an HDMI connector but a !HDMI display, we always
1110  * output RGB with 8 bpc.
1111  */
1112 static void drm_test_check_output_bpc_dvi(struct kunit *test)
1113 {
1114 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1115 	struct drm_modeset_acquire_ctx ctx;
1116 	struct drm_connector_state *conn_state;
1117 	struct drm_display_info *info;
1118 	struct drm_display_mode *preferred;
1119 	struct drm_connector *conn;
1120 	struct drm_device *drm;
1121 	struct drm_crtc *crtc;
1122 	int ret;
1123 
1124 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1125 				BIT(HDMI_COLORSPACE_RGB) |
1126 				BIT(HDMI_COLORSPACE_YUV422) |
1127 				BIT(HDMI_COLORSPACE_YUV444),
1128 				12,
1129 				&dummy_connector_hdmi_funcs,
1130 				test_edid_dvi_1080p);
1131 	KUNIT_ASSERT_NOT_NULL(test, priv);
1132 
1133 	drm = &priv->drm;
1134 	crtc = priv->crtc;
1135 	conn = &priv->connector;
1136 	info = &conn->display_info;
1137 	KUNIT_ASSERT_FALSE(test, info->is_hdmi);
1138 
1139 	preferred = find_preferred_mode(conn);
1140 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1141 
1142 	drm_modeset_acquire_init(&ctx, 0);
1143 
1144 retry_conn_enable:
1145 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
1146 						     crtc, conn,
1147 						     preferred,
1148 						     &ctx);
1149 	if (ret == -EDEADLK) {
1150 		ret = drm_modeset_backoff(&ctx);
1151 		if (!ret)
1152 			goto retry_conn_enable;
1153 	}
1154 	KUNIT_ASSERT_EQ(test, ret, 0);
1155 
1156 	conn_state = conn->state;
1157 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1158 
1159 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
1160 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1161 
1162 	drm_modeset_drop_locks(&ctx);
1163 	drm_modeset_acquire_fini(&ctx);
1164 }
1165 
1166 /*
1167  * Test that when doing a commit which would use RGB 8bpc, the TMDS
1168  * clock rate stored in the connector state is equal to the mode clock
1169  */
1170 static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test)
1171 {
1172 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1173 	struct drm_modeset_acquire_ctx ctx;
1174 	struct drm_connector_state *conn_state;
1175 	struct drm_display_mode *preferred;
1176 	struct drm_connector *conn;
1177 	struct drm_device *drm;
1178 	struct drm_crtc *crtc;
1179 	int ret;
1180 
1181 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1182 				BIT(HDMI_COLORSPACE_RGB),
1183 				8,
1184 				&dummy_connector_hdmi_funcs,
1185 				test_edid_hdmi_1080p_rgb_max_200mhz);
1186 	KUNIT_ASSERT_NOT_NULL(test, priv);
1187 
1188 	drm = &priv->drm;
1189 	crtc = priv->crtc;
1190 	conn = &priv->connector;
1191 	preferred = find_preferred_mode(conn);
1192 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1193 	KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
1194 
1195 	drm_modeset_acquire_init(&ctx, 0);
1196 
1197 retry_conn_enable:
1198 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
1199 						     crtc, conn,
1200 						     preferred,
1201 						     &ctx);
1202 	if (ret == -EDEADLK) {
1203 		ret = drm_modeset_backoff(&ctx);
1204 		if (!ret)
1205 			goto retry_conn_enable;
1206 	}
1207 	KUNIT_ASSERT_EQ(test, ret, 0);
1208 
1209 	conn_state = conn->state;
1210 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1211 
1212 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 8);
1213 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1214 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1000);
1215 
1216 	drm_modeset_drop_locks(&ctx);
1217 	drm_modeset_acquire_fini(&ctx);
1218 }
1219 
1220 /*
1221  * Test that when doing a commit which would use RGB 10bpc, the TMDS
1222  * clock rate stored in the connector state is equal to 1.25 times the
1223  * mode pixel clock
1224  */
1225 static void drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit *test)
1226 {
1227 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1228 	struct drm_modeset_acquire_ctx ctx;
1229 	struct drm_connector_state *conn_state;
1230 	struct drm_display_mode *preferred;
1231 	struct drm_connector *conn;
1232 	struct drm_device *drm;
1233 	struct drm_crtc *crtc;
1234 	int ret;
1235 
1236 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1237 				BIT(HDMI_COLORSPACE_RGB),
1238 				10,
1239 				&dummy_connector_hdmi_funcs,
1240 				test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz);
1241 	KUNIT_ASSERT_NOT_NULL(test, priv);
1242 
1243 	drm = &priv->drm;
1244 	crtc = priv->crtc;
1245 	conn = &priv->connector;
1246 	preferred = find_preferred_mode(conn);
1247 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1248 	KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
1249 
1250 	drm_modeset_acquire_init(&ctx, 0);
1251 
1252 retry_conn_enable:
1253 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
1254 						     crtc, conn,
1255 						     preferred,
1256 						     &ctx);
1257 	if (ret == -EDEADLK) {
1258 		ret = drm_modeset_backoff(&ctx);
1259 		if (!ret)
1260 			goto retry_conn_enable;
1261 	}
1262 	KUNIT_ASSERT_EQ(test, ret, 0);
1263 
1264 	conn_state = conn->state;
1265 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1266 
1267 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 10);
1268 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1269 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250);
1270 
1271 	drm_modeset_drop_locks(&ctx);
1272 	drm_modeset_acquire_fini(&ctx);
1273 }
1274 
1275 /*
1276  * Test that when doing a commit which would use RGB 12bpc, the TMDS
1277  * clock rate stored in the connector state is equal to 1.5 times the
1278  * mode pixel clock
1279  */
1280 static void drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test)
1281 {
1282 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1283 	struct drm_modeset_acquire_ctx ctx;
1284 	struct drm_connector_state *conn_state;
1285 	struct drm_display_mode *preferred;
1286 	struct drm_connector *conn;
1287 	struct drm_device *drm;
1288 	struct drm_crtc *crtc;
1289 	int ret;
1290 
1291 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1292 				BIT(HDMI_COLORSPACE_RGB),
1293 				12,
1294 				&dummy_connector_hdmi_funcs,
1295 				test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz);
1296 	KUNIT_ASSERT_NOT_NULL(test, priv);
1297 
1298 	drm = &priv->drm;
1299 	crtc = priv->crtc;
1300 	conn = &priv->connector;
1301 	preferred = find_preferred_mode(conn);
1302 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1303 	KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
1304 
1305 	drm_modeset_acquire_init(&ctx, 0);
1306 
1307 retry_conn_enable:
1308 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
1309 						     crtc, conn,
1310 						     preferred,
1311 						     &ctx);
1312 	if (ret == -EDEADLK) {
1313 		ret = drm_modeset_backoff(&ctx);
1314 		if (!ret)
1315 			goto retry_conn_enable;
1316 	}
1317 	KUNIT_ASSERT_EQ(test, ret, 0);
1318 
1319 	conn_state = conn->state;
1320 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1321 
1322 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 12);
1323 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1324 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1500);
1325 
1326 	drm_modeset_drop_locks(&ctx);
1327 	drm_modeset_acquire_fini(&ctx);
1328 }
1329 
1330 /*
1331  * Test that if we filter a rate through our hook, it's indeed rejected
1332  * by the whole atomic_check logic.
1333  *
1334  * We do so by first doing a commit on the pipeline to make sure that it
1335  * works, change the HDMI helpers pointer, and then try the same commit
1336  * again to see if it fails as it should.
1337  */
1338 static void drm_test_check_hdmi_funcs_reject_rate(struct kunit *test)
1339 {
1340 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1341 	struct drm_modeset_acquire_ctx ctx;
1342 	struct drm_atomic_state *state;
1343 	struct drm_display_mode *preferred;
1344 	struct drm_crtc_state *crtc_state;
1345 	struct drm_connector *conn;
1346 	struct drm_device *drm;
1347 	struct drm_crtc *crtc;
1348 	int ret;
1349 
1350 	priv = drm_kunit_helper_connector_hdmi_init(test,
1351 						    BIT(HDMI_COLORSPACE_RGB),
1352 						    8);
1353 	KUNIT_ASSERT_NOT_NULL(test, priv);
1354 
1355 	drm = &priv->drm;
1356 	crtc = priv->crtc;
1357 	conn = &priv->connector;
1358 
1359 	preferred = find_preferred_mode(conn);
1360 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1361 
1362 	drm_modeset_acquire_init(&ctx, 0);
1363 
1364 retry_conn_enable:
1365 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
1366 						     crtc, conn,
1367 						     preferred,
1368 						     &ctx);
1369 	if (ret == -EDEADLK) {
1370 		ret = drm_modeset_backoff(&ctx);
1371 		if (!ret)
1372 			goto retry_conn_enable;
1373 	}
1374 	KUNIT_ASSERT_EQ(test, ret, 0);
1375 
1376 	/* You shouldn't be doing that at home. */
1377 	conn->hdmi.funcs = &reject_connector_hdmi_funcs;
1378 
1379 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
1380 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1381 
1382 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
1383 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1384 
1385 	crtc_state->connectors_changed = true;
1386 
1387 	ret = drm_atomic_check_only(state);
1388 	KUNIT_EXPECT_LT(test, ret, 0);
1389 
1390 	drm_modeset_drop_locks(&ctx);
1391 	drm_modeset_acquire_fini(&ctx);
1392 }
1393 
1394 /*
1395  * Test that if:
1396  * - We have an HDMI connector supporting RGB only
1397  * - The chosen mode has a TMDS character rate higher than the display
1398  *   supports in RGB/12bpc
1399  * - The chosen mode has a TMDS character rate lower than the display
1400  *   supports in RGB/10bpc.
1401  *
1402  * Then we will pick the latter, and the computed TMDS character rate
1403  * will be equal to 1.25 times the mode pixel clock.
1404  */
1405 static void drm_test_check_max_tmds_rate_bpc_fallback_rgb(struct kunit *test)
1406 {
1407 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1408 	struct drm_modeset_acquire_ctx ctx;
1409 	struct drm_connector_state *conn_state;
1410 	struct drm_display_info *info;
1411 	struct drm_display_mode *preferred;
1412 	unsigned long long rate;
1413 	struct drm_connector *conn;
1414 	struct drm_device *drm;
1415 	struct drm_crtc *crtc;
1416 	int ret;
1417 
1418 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1419 				BIT(HDMI_COLORSPACE_RGB),
1420 				12,
1421 				&dummy_connector_hdmi_funcs,
1422 				test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz);
1423 	KUNIT_ASSERT_NOT_NULL(test, priv);
1424 
1425 	drm = &priv->drm;
1426 	crtc = priv->crtc;
1427 	conn = &priv->connector;
1428 	info = &conn->display_info;
1429 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1430 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1431 
1432 	preferred = find_preferred_mode(conn);
1433 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1434 	KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
1435 
1436 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1437 	KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1438 
1439 	rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB);
1440 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1441 
1442 	drm_modeset_acquire_init(&ctx, 0);
1443 
1444 retry_conn_enable:
1445 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
1446 						     crtc, conn,
1447 						     preferred,
1448 						     &ctx);
1449 	if (ret == -EDEADLK) {
1450 		ret = drm_modeset_backoff(&ctx);
1451 		if (!ret)
1452 			goto retry_conn_enable;
1453 	}
1454 	KUNIT_EXPECT_EQ(test, ret, 0);
1455 
1456 	conn_state = conn->state;
1457 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1458 
1459 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10);
1460 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1461 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250);
1462 
1463 	drm_modeset_drop_locks(&ctx);
1464 	drm_modeset_acquire_fini(&ctx);
1465 }
1466 
1467 /*
1468  * Test that if:
1469  * - We have an HDMI connector and a display supporting both RGB and YUV420
1470  * - The chosen mode can be supported in YUV420 output format only
1471  * - The chosen mode has a TMDS character rate higher than the display
1472  *   supports in YUV420/12bpc
1473  * - The chosen mode has a TMDS character rate lower than the display
1474  *   supports in YUV420/10bpc.
1475  *
1476  * Then we will pick the latter, and the computed TMDS character rate
1477  * will be equal to 1.25 * 0.5 times the mode pixel clock.
1478  */
1479 static void drm_test_check_max_tmds_rate_bpc_fallback_yuv420(struct kunit *test)
1480 {
1481 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1482 	struct drm_modeset_acquire_ctx ctx;
1483 	struct drm_connector_state *conn_state;
1484 	struct drm_display_info *info;
1485 	struct drm_display_mode *yuv420_only_mode;
1486 	unsigned long long rate;
1487 	struct drm_connector *conn;
1488 	struct drm_device *drm;
1489 	struct drm_crtc *crtc;
1490 	int ret;
1491 
1492 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1493 				BIT(HDMI_COLORSPACE_RGB) |
1494 				BIT(HDMI_COLORSPACE_YUV420),
1495 				12,
1496 				&dummy_connector_hdmi_funcs,
1497 				test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz);
1498 	KUNIT_ASSERT_NOT_NULL(test, priv);
1499 
1500 	drm = &priv->drm;
1501 	crtc = priv->crtc;
1502 	conn = &priv->connector;
1503 	info = &conn->display_info;
1504 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1505 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1506 	KUNIT_ASSERT_TRUE(test, conn->ycbcr_420_allowed);
1507 
1508 	yuv420_only_mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95);
1509 	KUNIT_ASSERT_NOT_NULL(test, yuv420_only_mode);
1510 	KUNIT_ASSERT_TRUE(test, drm_mode_is_420_only(info, yuv420_only_mode));
1511 
1512 	rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 12, HDMI_COLORSPACE_YUV420);
1513 	KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1514 
1515 	rate = drm_hdmi_compute_mode_clock(yuv420_only_mode, 10, HDMI_COLORSPACE_YUV420);
1516 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1517 
1518 	drm_modeset_acquire_init(&ctx, 0);
1519 
1520 retry_conn_enable:
1521 	ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn,
1522 						     yuv420_only_mode, &ctx);
1523 	if (ret == -EDEADLK) {
1524 		ret = drm_modeset_backoff(&ctx);
1525 		if (!ret)
1526 			goto retry_conn_enable;
1527 	}
1528 	KUNIT_EXPECT_EQ(test, ret, 0);
1529 
1530 	conn_state = conn->state;
1531 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1532 
1533 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10);
1534 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_YUV420);
1535 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, yuv420_only_mode->clock * 625);
1536 
1537 	drm_modeset_drop_locks(&ctx);
1538 	drm_modeset_acquire_fini(&ctx);
1539 }
1540 
1541 /*
1542  * Test that if:
1543  * - We have an HDMI connector supporting both RGB and YUV422 and up to
1544  *   12 bpc
1545  * - The chosen mode has a TMDS character rate higher than the display
1546  *   supports in RGB/12bpc but lower than the display supports in
1547  *   RGB/10bpc
1548  * - The chosen mode has a TMDS character rate lower than the display
1549  *   supports in YUV422/12bpc.
1550  *
1551  * Then we will prefer to keep the RGB format with a lower bpc over
1552  * picking YUV422.
1553  */
1554 static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422(struct kunit *test)
1555 {
1556 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1557 	struct drm_modeset_acquire_ctx ctx;
1558 	struct drm_connector_state *conn_state;
1559 	struct drm_display_info *info;
1560 	struct drm_display_mode *preferred;
1561 	unsigned long long rate;
1562 	struct drm_connector *conn;
1563 	struct drm_device *drm;
1564 	struct drm_crtc *crtc;
1565 	int ret;
1566 
1567 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1568 				BIT(HDMI_COLORSPACE_RGB) |
1569 				BIT(HDMI_COLORSPACE_YUV422) |
1570 				BIT(HDMI_COLORSPACE_YUV444),
1571 				12,
1572 				&dummy_connector_hdmi_funcs,
1573 				test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz);
1574 	KUNIT_ASSERT_NOT_NULL(test, priv);
1575 
1576 	drm = &priv->drm;
1577 	crtc = priv->crtc;
1578 	conn = &priv->connector;
1579 	info = &conn->display_info;
1580 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1581 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1582 
1583 	preferred = find_preferred_mode(conn);
1584 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1585 	KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
1586 
1587 	rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB);
1588 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1589 
1590 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1591 	KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1592 
1593 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
1594 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1595 
1596 	drm_modeset_acquire_init(&ctx, 0);
1597 
1598 retry_conn_enable:
1599 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
1600 						     crtc, conn,
1601 						     preferred,
1602 						     &ctx);
1603 	if (ret == -EDEADLK) {
1604 		ret = drm_modeset_backoff(&ctx);
1605 		if (!ret)
1606 			goto retry_conn_enable;
1607 	}
1608 	KUNIT_EXPECT_EQ(test, ret, 0);
1609 
1610 	conn_state = conn->state;
1611 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1612 
1613 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10);
1614 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1615 
1616 	drm_modeset_drop_locks(&ctx);
1617 	drm_modeset_acquire_fini(&ctx);
1618 }
1619 
1620 /*
1621  * Test that if:
1622  * - We have an HDMI connector supporting both RGB and YUV420 and up to
1623  *   12 bpc
1624  * - The chosen mode has a TMDS character rate higher than the display
1625  *   supports in RGB/10bpc but lower than the display supports in
1626  *   RGB/8bpc
1627  * - The chosen mode has a TMDS character rate lower than the display
1628  *   supports in YUV420/12bpc.
1629  *
1630  * Then we will prefer to keep the RGB format with a lower bpc over
1631  * picking YUV420.
1632  */
1633 static void drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420(struct kunit *test)
1634 {
1635 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1636 	struct drm_modeset_acquire_ctx ctx;
1637 	struct drm_connector_state *conn_state;
1638 	struct drm_display_info *info;
1639 	struct drm_display_mode *preferred;
1640 	unsigned long long rate;
1641 	struct drm_connector *conn;
1642 	struct drm_device *drm;
1643 	struct drm_crtc *crtc;
1644 	int ret;
1645 
1646 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1647 				BIT(HDMI_COLORSPACE_RGB) |
1648 				BIT(HDMI_COLORSPACE_YUV420),
1649 				12,
1650 				&dummy_connector_hdmi_funcs,
1651 				test_edid_hdmi_4k_rgb_yuv420_dc_max_340mhz);
1652 	KUNIT_ASSERT_NOT_NULL(test, priv);
1653 
1654 	drm = &priv->drm;
1655 	crtc = priv->crtc;
1656 	conn = &priv->connector;
1657 	info = &conn->display_info;
1658 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1659 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1660 	KUNIT_ASSERT_TRUE(test, conn->ycbcr_420_allowed);
1661 
1662 	preferred = find_preferred_mode(conn);
1663 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1664 	KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
1665 	KUNIT_ASSERT_TRUE(test, drm_mode_is_420_also(info, preferred));
1666 
1667 	rate = drm_hdmi_compute_mode_clock(preferred, 8, HDMI_COLORSPACE_RGB);
1668 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1669 
1670 	rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB);
1671 	KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1672 
1673 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV420);
1674 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1675 
1676 	drm_modeset_acquire_init(&ctx, 0);
1677 
1678 retry_conn_enable:
1679 	ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn,
1680 						     preferred, &ctx);
1681 	if (ret == -EDEADLK) {
1682 		ret = drm_modeset_backoff(&ctx);
1683 		if (!ret)
1684 			goto retry_conn_enable;
1685 	}
1686 	KUNIT_EXPECT_EQ(test, ret, 0);
1687 
1688 	conn_state = conn->state;
1689 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1690 
1691 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
1692 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1693 
1694 	drm_modeset_drop_locks(&ctx);
1695 	drm_modeset_acquire_fini(&ctx);
1696 }
1697 
1698 /*
1699  * Test that if a driver supports only RGB, but the chosen mode can be
1700  * supported by the screen only in YUV420 output format, we end up with
1701  * unsuccessful fallback attempts.
1702  */
1703 static void drm_test_check_driver_unsupported_fallback_yuv420(struct kunit *test)
1704 {
1705 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1706 	struct drm_modeset_acquire_ctx ctx;
1707 	struct drm_connector_state *conn_state;
1708 	struct drm_crtc_state *crtc_state;
1709 	struct drm_atomic_state *state;
1710 	struct drm_display_info *info;
1711 	struct drm_display_mode *preferred, *yuv420_only_mode;
1712 	struct drm_connector *conn;
1713 	struct drm_device *drm;
1714 	struct drm_crtc *crtc;
1715 	int ret;
1716 
1717 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1718 				BIT(HDMI_COLORSPACE_RGB),
1719 				12,
1720 				&dummy_connector_hdmi_funcs,
1721 				test_edid_hdmi_1080p_rgb_yuv_4k_yuv420_dc_max_200mhz);
1722 	KUNIT_ASSERT_NOT_NULL(test, priv);
1723 
1724 	drm = &priv->drm;
1725 	crtc = priv->crtc;
1726 	conn = &priv->connector;
1727 	info = &conn->display_info;
1728 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1729 	KUNIT_ASSERT_FALSE(test, conn->ycbcr_420_allowed);
1730 
1731 	preferred = find_preferred_mode(conn);
1732 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1733 	KUNIT_ASSERT_FALSE(test, drm_mode_is_420_also(info, preferred));
1734 
1735 	yuv420_only_mode = drm_kunit_display_mode_from_cea_vic(test, drm, 95);
1736 	KUNIT_ASSERT_NOT_NULL(test, yuv420_only_mode);
1737 	KUNIT_ASSERT_TRUE(test, drm_mode_is_420_only(info, yuv420_only_mode));
1738 
1739 	drm_modeset_acquire_init(&ctx, 0);
1740 
1741 retry_conn_enable:
1742 	ret = drm_kunit_helper_enable_crtc_connector(test, drm, crtc, conn,
1743 						     preferred, &ctx);
1744 	if (ret == -EDEADLK) {
1745 		ret = drm_modeset_backoff(&ctx);
1746 		if (!ret)
1747 			goto retry_conn_enable;
1748 	}
1749 	KUNIT_EXPECT_EQ(test, ret, 0);
1750 
1751 	conn_state = conn->state;
1752 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1753 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1754 
1755 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
1756 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1757 
1758 retry_crtc_state:
1759 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
1760 	if (PTR_ERR(crtc_state) == -EDEADLK) {
1761 		drm_atomic_state_clear(state);
1762 		ret = drm_modeset_backoff(&ctx);
1763 		if (!ret)
1764 			goto retry_crtc_state;
1765 	}
1766 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1767 
1768 	ret = drm_atomic_set_mode_for_crtc(crtc_state, yuv420_only_mode);
1769 	KUNIT_EXPECT_EQ(test, ret, 0);
1770 
1771 	ret = drm_atomic_check_only(state);
1772 	if (ret == -EDEADLK) {
1773 		drm_atomic_state_clear(state);
1774 		ret = drm_modeset_backoff(&ctx);
1775 		if (!ret)
1776 			goto retry_crtc_state;
1777 	}
1778 	KUNIT_ASSERT_LT(test, ret, 0);
1779 
1780 	drm_modeset_drop_locks(&ctx);
1781 	drm_modeset_acquire_fini(&ctx);
1782 }
1783 
1784 /*
1785  * Test that if a driver and screen supports RGB and YUV formats, and we
1786  * try to set the VIC 1 mode, we end up with 8bpc RGB even if we could
1787  * have had a higher bpc.
1788  */
1789 static void drm_test_check_output_bpc_format_vic_1(struct kunit *test)
1790 {
1791 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1792 	struct drm_modeset_acquire_ctx ctx;
1793 	struct drm_connector_state *conn_state;
1794 	struct drm_display_info *info;
1795 	struct drm_display_mode *mode;
1796 	unsigned long long rate;
1797 	struct drm_connector *conn;
1798 	struct drm_device *drm;
1799 	struct drm_crtc *crtc;
1800 	int ret;
1801 
1802 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1803 				BIT(HDMI_COLORSPACE_RGB) |
1804 				BIT(HDMI_COLORSPACE_YUV422) |
1805 				BIT(HDMI_COLORSPACE_YUV444),
1806 				12,
1807 				&dummy_connector_hdmi_funcs,
1808 				test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz);
1809 	KUNIT_ASSERT_NOT_NULL(test, priv);
1810 
1811 	drm = &priv->drm;
1812 	conn = &priv->connector;
1813 	info = &conn->display_info;
1814 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1815 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1816 
1817 	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
1818 	KUNIT_ASSERT_NOT_NULL(test, mode);
1819 
1820 	/*
1821 	 * NOTE: We can't use drm_hdmi_compute_mode_clock()
1822 	 * here because we're trying to get the rate of an invalid
1823 	 * configuration.
1824 	 *
1825 	 * Thus, we have to calculate the rate by hand.
1826 	 */
1827 	rate = mode->clock * 1500;
1828 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1829 
1830 	drm_modeset_acquire_init(&ctx, 0);
1831 
1832 	crtc = priv->crtc;
1833 
1834 retry_conn_enable:
1835 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
1836 						     crtc, conn,
1837 						     mode,
1838 						     &ctx);
1839 	if (ret == -EDEADLK) {
1840 		ret = drm_modeset_backoff(&ctx);
1841 		if (!ret)
1842 			goto retry_conn_enable;
1843 	}
1844 	KUNIT_EXPECT_EQ(test, ret, 0);
1845 
1846 	conn_state = conn->state;
1847 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1848 
1849 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
1850 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1851 
1852 	drm_modeset_drop_locks(&ctx);
1853 	drm_modeset_acquire_fini(&ctx);
1854 }
1855 
1856 /*
1857  * Test that if a driver supports only RGB but the screen also supports
1858  * YUV formats, we only end up with an RGB format.
1859  */
1860 static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test)
1861 {
1862 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1863 	struct drm_modeset_acquire_ctx ctx;
1864 	struct drm_connector_state *conn_state;
1865 	struct drm_display_info *info;
1866 	struct drm_display_mode *preferred;
1867 	unsigned long long rate;
1868 	struct drm_connector *conn;
1869 	struct drm_device *drm;
1870 	struct drm_crtc *crtc;
1871 	int ret;
1872 
1873 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1874 				BIT(HDMI_COLORSPACE_RGB),
1875 				12,
1876 				&dummy_connector_hdmi_funcs,
1877 				test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz);
1878 	KUNIT_ASSERT_NOT_NULL(test, priv);
1879 
1880 	drm = &priv->drm;
1881 	crtc = priv->crtc;
1882 	conn = &priv->connector;
1883 	info = &conn->display_info;
1884 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1885 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1886 
1887 	preferred = find_preferred_mode(conn);
1888 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1889 
1890 	/*
1891 	 * We're making sure that YUV422 would be the preferred option
1892 	 * here: we're always favouring higher bpc, we can't have RGB
1893 	 * because the TMDS character rate exceeds the maximum supported
1894 	 * by the display, and YUV422 works for that display.
1895 	 *
1896 	 * But since the driver only supports RGB, we should fallback to
1897 	 * a lower bpc with RGB.
1898 	 */
1899 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1900 	KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1901 
1902 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
1903 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1904 
1905 	drm_modeset_acquire_init(&ctx, 0);
1906 
1907 retry_conn_enable:
1908 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
1909 						     crtc, conn,
1910 						     preferred,
1911 						     &ctx);
1912 	if (ret == -EDEADLK) {
1913 		ret = drm_modeset_backoff(&ctx);
1914 		if (!ret)
1915 			goto retry_conn_enable;
1916 	}
1917 	KUNIT_EXPECT_EQ(test, ret, 0);
1918 
1919 	conn_state = conn->state;
1920 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1921 
1922 	KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12);
1923 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1924 
1925 	drm_modeset_drop_locks(&ctx);
1926 	drm_modeset_acquire_fini(&ctx);
1927 }
1928 
1929 /*
1930  * Test that if a screen supports only RGB but the driver also supports
1931  * YUV formats, we only end up with an RGB format.
1932  */
1933 static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test)
1934 {
1935 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1936 	struct drm_modeset_acquire_ctx ctx;
1937 	struct drm_connector_state *conn_state;
1938 	struct drm_display_info *info;
1939 	struct drm_display_mode *preferred;
1940 	unsigned long long rate;
1941 	struct drm_connector *conn;
1942 	struct drm_device *drm;
1943 	struct drm_crtc *crtc;
1944 	int ret;
1945 
1946 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
1947 				BIT(HDMI_COLORSPACE_RGB) |
1948 				BIT(HDMI_COLORSPACE_YUV422) |
1949 				BIT(HDMI_COLORSPACE_YUV444),
1950 				12,
1951 				&dummy_connector_hdmi_funcs,
1952 				test_edid_hdmi_1080p_rgb_max_200mhz);
1953 	KUNIT_ASSERT_NOT_NULL(test, priv);
1954 
1955 	drm = &priv->drm;
1956 	crtc = priv->crtc;
1957 	conn = &priv->connector;
1958 	info = &conn->display_info;
1959 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1960 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1961 
1962 	preferred = find_preferred_mode(conn);
1963 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1964 
1965 	/*
1966 	 * We're making sure that YUV422 would be the preferred option
1967 	 * here: we're always favouring higher bpc, we can't have RGB
1968 	 * because the TMDS character rate exceeds the maximum supported
1969 	 * by the display, and YUV422 works for that display.
1970 	 *
1971 	 * But since the display only supports RGB, we should fallback to
1972 	 * a lower bpc with RGB.
1973 	 */
1974 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1975 	KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1976 
1977 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
1978 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1979 
1980 	drm_modeset_acquire_init(&ctx, 0);
1981 
1982 retry_conn_enable:
1983 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
1984 						     crtc, conn,
1985 						     preferred,
1986 						     &ctx);
1987 	if (ret == -EDEADLK) {
1988 		ret = drm_modeset_backoff(&ctx);
1989 		if (!ret)
1990 			goto retry_conn_enable;
1991 	}
1992 	KUNIT_EXPECT_EQ(test, ret, 0);
1993 
1994 	conn_state = conn->state;
1995 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1996 
1997 	KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12);
1998 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1999 
2000 	drm_modeset_drop_locks(&ctx);
2001 	drm_modeset_acquire_fini(&ctx);
2002 }
2003 
2004 /*
2005  * Test that if a display supports higher bpc but the driver only
2006  * supports 8 bpc, we only end up with 8 bpc even if we could have had a
2007  * higher bpc.
2008  */
2009 static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test)
2010 {
2011 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2012 	struct drm_modeset_acquire_ctx ctx;
2013 	struct drm_connector_state *conn_state;
2014 	struct drm_display_info *info;
2015 	struct drm_display_mode *preferred;
2016 	unsigned long long rate;
2017 	struct drm_connector *conn;
2018 	struct drm_device *drm;
2019 	struct drm_crtc *crtc;
2020 	int ret;
2021 
2022 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
2023 				BIT(HDMI_COLORSPACE_RGB),
2024 				8,
2025 				&dummy_connector_hdmi_funcs,
2026 				test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz);
2027 	KUNIT_ASSERT_NOT_NULL(test, priv);
2028 
2029 	drm = &priv->drm;
2030 	crtc = priv->crtc;
2031 	conn = &priv->connector;
2032 	info = &conn->display_info;
2033 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
2034 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
2035 
2036 	preferred = find_preferred_mode(conn);
2037 	KUNIT_ASSERT_NOT_NULL(test, preferred);
2038 
2039 	/*
2040 	 * We're making sure that we have headroom on the TMDS character
2041 	 * clock to actually use 12bpc.
2042 	 */
2043 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
2044 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
2045 
2046 	drm_modeset_acquire_init(&ctx, 0);
2047 
2048 retry_conn_enable:
2049 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
2050 						     crtc, conn,
2051 						     preferred,
2052 						     &ctx);
2053 	if (ret == -EDEADLK) {
2054 		ret = drm_modeset_backoff(&ctx);
2055 		if (!ret)
2056 			goto retry_conn_enable;
2057 	}
2058 	KUNIT_EXPECT_EQ(test, ret, 0);
2059 
2060 	conn_state = conn->state;
2061 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
2062 
2063 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
2064 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
2065 
2066 	drm_modeset_drop_locks(&ctx);
2067 	drm_modeset_acquire_fini(&ctx);
2068 }
2069 
2070 /*
2071  * Test that if a driver supports higher bpc but the display only
2072  * supports 8 bpc, we only end up with 8 bpc even if we could have had a
2073  * higher bpc.
2074  */
2075 static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *test)
2076 {
2077 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2078 	struct drm_modeset_acquire_ctx ctx;
2079 	struct drm_connector_state *conn_state;
2080 	struct drm_display_info *info;
2081 	struct drm_display_mode *preferred;
2082 	unsigned long long rate;
2083 	struct drm_connector *conn;
2084 	struct drm_device *drm;
2085 	struct drm_crtc *crtc;
2086 	int ret;
2087 
2088 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
2089 				BIT(HDMI_COLORSPACE_RGB) |
2090 				BIT(HDMI_COLORSPACE_YUV422) |
2091 				BIT(HDMI_COLORSPACE_YUV444),
2092 				12,
2093 				&dummy_connector_hdmi_funcs,
2094 				test_edid_hdmi_1080p_rgb_max_340mhz);
2095 	KUNIT_ASSERT_NOT_NULL(test, priv);
2096 
2097 	drm = &priv->drm;
2098 	crtc = priv->crtc;
2099 	conn = &priv->connector;
2100 	info = &conn->display_info;
2101 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
2102 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
2103 
2104 	preferred = find_preferred_mode(conn);
2105 	KUNIT_ASSERT_NOT_NULL(test, preferred);
2106 
2107 	/*
2108 	 * We're making sure that we have headroom on the TMDS character
2109 	 * clock to actually use 12bpc.
2110 	 */
2111 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
2112 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
2113 
2114 	drm_modeset_acquire_init(&ctx, 0);
2115 
2116 retry_conn_enable:
2117 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
2118 						     crtc, conn,
2119 						     preferred,
2120 						     &ctx);
2121 	if (ret == -EDEADLK) {
2122 		ret = drm_modeset_backoff(&ctx);
2123 		if (!ret)
2124 			goto retry_conn_enable;
2125 	}
2126 	KUNIT_EXPECT_EQ(test, ret, 0);
2127 
2128 	conn_state = conn->state;
2129 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
2130 
2131 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
2132 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
2133 
2134 	drm_modeset_drop_locks(&ctx);
2135 	drm_modeset_acquire_fini(&ctx);
2136 }
2137 
2138 /* Test that atomic check succeeds when disabling a connector. */
2139 static void drm_test_check_disable_connector(struct kunit *test)
2140 {
2141 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2142 	struct drm_modeset_acquire_ctx ctx;
2143 	struct drm_connector_state *conn_state;
2144 	struct drm_crtc_state *crtc_state;
2145 	struct drm_atomic_state *state;
2146 	struct drm_display_mode *preferred;
2147 	struct drm_connector *conn;
2148 	struct drm_device *drm;
2149 	struct drm_crtc *crtc;
2150 	int ret;
2151 
2152 	priv = drm_kunit_helper_connector_hdmi_init(test,
2153 						    BIT(HDMI_COLORSPACE_RGB),
2154 						    8);
2155 	KUNIT_ASSERT_NOT_NULL(test, priv);
2156 
2157 	drm_modeset_acquire_init(&ctx, 0);
2158 
2159 	conn = &priv->connector;
2160 	preferred = find_preferred_mode(conn);
2161 	KUNIT_ASSERT_NOT_NULL(test, preferred);
2162 
2163 	drm = &priv->drm;
2164 	crtc = priv->crtc;
2165 
2166 retry_conn_enable:
2167 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
2168 						     crtc, conn,
2169 						     preferred,
2170 						     &ctx);
2171 	if (ret == -EDEADLK) {
2172 		ret = drm_modeset_backoff(&ctx);
2173 		if (!ret)
2174 			goto retry_conn_enable;
2175 	}
2176 	KUNIT_ASSERT_EQ(test, ret, 0);
2177 
2178 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
2179 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
2180 
2181 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
2182 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
2183 
2184 	crtc_state->active = false;
2185 	ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
2186 	KUNIT_EXPECT_EQ(test, ret, 0);
2187 
2188 	conn_state = drm_atomic_get_connector_state(state, conn);
2189 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
2190 
2191 	ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
2192 	KUNIT_EXPECT_EQ(test, ret, 0);
2193 
2194 	ret = drm_atomic_check_only(state);
2195 	KUNIT_ASSERT_EQ(test, ret, 0);
2196 
2197 	drm_modeset_drop_locks(&ctx);
2198 	drm_modeset_acquire_fini(&ctx);
2199 }
2200 
2201 static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = {
2202 	KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode),
2203 	KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode_vic_1),
2204 	KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode),
2205 	KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode_vic_1),
2206 	KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode),
2207 	KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode_vic_1),
2208 	KUNIT_CASE_PARAM(drm_test_check_broadcast_rgb_cea_mode_yuv420,
2209 			 check_broadcast_rgb_cea_mode_yuv420_gen_params),
2210 	KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_changed),
2211 	KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_not_changed),
2212 	KUNIT_CASE(drm_test_check_disable_connector),
2213 	KUNIT_CASE(drm_test_check_hdmi_funcs_reject_rate),
2214 	KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_rgb),
2215 	KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_yuv420),
2216 	KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422),
2217 	KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420),
2218 	KUNIT_CASE(drm_test_check_driver_unsupported_fallback_yuv420),
2219 	KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_changed),
2220 	KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_not_changed),
2221 	KUNIT_CASE(drm_test_check_output_bpc_dvi),
2222 	KUNIT_CASE(drm_test_check_output_bpc_format_vic_1),
2223 	KUNIT_CASE(drm_test_check_output_bpc_format_display_8bpc_only),
2224 	KUNIT_CASE(drm_test_check_output_bpc_format_display_rgb_only),
2225 	KUNIT_CASE(drm_test_check_output_bpc_format_driver_8bpc_only),
2226 	KUNIT_CASE(drm_test_check_output_bpc_format_driver_rgb_only),
2227 	KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_8bpc),
2228 	KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_10bpc),
2229 	KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_12bpc),
2230 	/*
2231 	 * TODO: We should have tests to check that a change in the
2232 	 * format triggers a CRTC mode change just like we do for the
2233 	 * RGB Quantization and BPC.
2234 	 *
2235 	 * However, we don't have any way to control which format gets
2236 	 * picked up aside from changing the BPC or mode which would
2237 	 * already trigger a mode change.
2238 	 */
2239 	{ }
2240 };
2241 
2242 static struct kunit_suite drm_atomic_helper_connector_hdmi_check_test_suite = {
2243 	.name		= "drm_atomic_helper_connector_hdmi_check",
2244 	.test_cases	= drm_atomic_helper_connector_hdmi_check_tests,
2245 };
2246 
2247 /*
2248  * Test that the value of the Broadcast RGB property out of reset is set
2249  * to auto.
2250  */
2251 static void drm_test_check_broadcast_rgb_value(struct kunit *test)
2252 {
2253 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2254 	struct drm_connector_state *conn_state;
2255 	struct drm_connector *conn;
2256 
2257 	priv = drm_kunit_helper_connector_hdmi_init(test,
2258 						    BIT(HDMI_COLORSPACE_RGB),
2259 						    8);
2260 	KUNIT_ASSERT_NOT_NULL(test, priv);
2261 
2262 	conn = &priv->connector;
2263 	conn_state = conn->state;
2264 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_AUTO);
2265 }
2266 
2267 /*
2268  * Test that if the connector was initialised with a maximum bpc of 8,
2269  * the value of the max_bpc and max_requested_bpc properties out of
2270  * reset are also set to 8, and output_bpc is set to 0 and will be
2271  * filled at atomic_check time.
2272  */
2273 static void drm_test_check_bpc_8_value(struct kunit *test)
2274 {
2275 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2276 	struct drm_connector_state *conn_state;
2277 	struct drm_connector *conn;
2278 
2279 	priv = drm_kunit_helper_connector_hdmi_init(test,
2280 						    BIT(HDMI_COLORSPACE_RGB),
2281 						    8);
2282 	KUNIT_ASSERT_NOT_NULL(test, priv);
2283 
2284 	conn = &priv->connector;
2285 	conn_state = conn->state;
2286 	KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 8);
2287 	KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 8);
2288 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0);
2289 }
2290 
2291 /*
2292  * Test that if the connector was initialised with a maximum bpc of 10,
2293  * the value of the max_bpc and max_requested_bpc properties out of
2294  * reset are also set to 10, and output_bpc is set to 0 and will be
2295  * filled at atomic_check time.
2296  */
2297 static void drm_test_check_bpc_10_value(struct kunit *test)
2298 {
2299 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2300 	struct drm_connector_state *conn_state;
2301 	struct drm_connector *conn;
2302 
2303 	priv = drm_kunit_helper_connector_hdmi_init(test,
2304 						    BIT(HDMI_COLORSPACE_RGB),
2305 						    10);
2306 	KUNIT_ASSERT_NOT_NULL(test, priv);
2307 
2308 	conn = &priv->connector;
2309 	conn_state = conn->state;
2310 	KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 10);
2311 	KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 10);
2312 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0);
2313 }
2314 
2315 /*
2316  * Test that if the connector was initialised with a maximum bpc of 12,
2317  * the value of the max_bpc and max_requested_bpc properties out of
2318  * reset are also set to 12, and output_bpc is set to 0 and will be
2319  * filled at atomic_check time.
2320  */
2321 static void drm_test_check_bpc_12_value(struct kunit *test)
2322 {
2323 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2324 	struct drm_connector_state *conn_state;
2325 	struct drm_connector *conn;
2326 
2327 	priv = drm_kunit_helper_connector_hdmi_init(test,
2328 						    BIT(HDMI_COLORSPACE_RGB),
2329 						    12);
2330 	KUNIT_ASSERT_NOT_NULL(test, priv);
2331 
2332 	conn = &priv->connector;
2333 	conn_state = conn->state;
2334 	KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 12);
2335 	KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 12);
2336 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0);
2337 }
2338 
2339 /*
2340  * Test that the value of the output format property out of reset is set
2341  * to RGB, even if the driver supports more than that.
2342  */
2343 static void drm_test_check_format_value(struct kunit *test)
2344 {
2345 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2346 	struct drm_connector_state *conn_state;
2347 	struct drm_connector *conn;
2348 
2349 	priv = drm_kunit_helper_connector_hdmi_init(test,
2350 						    BIT(HDMI_COLORSPACE_RGB) |
2351 						    BIT(HDMI_COLORSPACE_YUV422) |
2352 						    BIT(HDMI_COLORSPACE_YUV444),
2353 						    8);
2354 	KUNIT_ASSERT_NOT_NULL(test, priv);
2355 
2356 	conn = &priv->connector;
2357 	conn_state = conn->state;
2358 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, 0);
2359 }
2360 
2361 /*
2362  * Test that the value of the output format property out of reset is set
2363  * to 0, and will be computed at atomic_check time.
2364  */
2365 static void drm_test_check_tmds_char_value(struct kunit *test)
2366 {
2367 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2368 	struct drm_connector_state *conn_state;
2369 	struct drm_connector *conn;
2370 
2371 	priv = drm_kunit_helper_connector_hdmi_init(test,
2372 						    BIT(HDMI_COLORSPACE_RGB) |
2373 						    BIT(HDMI_COLORSPACE_YUV422) |
2374 						    BIT(HDMI_COLORSPACE_YUV444),
2375 						    12);
2376 	KUNIT_ASSERT_NOT_NULL(test, priv);
2377 
2378 	conn = &priv->connector;
2379 	conn_state = conn->state;
2380 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, 0);
2381 }
2382 
2383 static struct kunit_case drm_atomic_helper_connector_hdmi_reset_tests[] = {
2384 	KUNIT_CASE(drm_test_check_broadcast_rgb_value),
2385 	KUNIT_CASE(drm_test_check_bpc_8_value),
2386 	KUNIT_CASE(drm_test_check_bpc_10_value),
2387 	KUNIT_CASE(drm_test_check_bpc_12_value),
2388 	KUNIT_CASE(drm_test_check_format_value),
2389 	KUNIT_CASE(drm_test_check_tmds_char_value),
2390 	{ }
2391 };
2392 
2393 static struct kunit_suite drm_atomic_helper_connector_hdmi_reset_test_suite = {
2394 	.name		= "drm_atomic_helper_connector_hdmi_reset",
2395 	.test_cases	= drm_atomic_helper_connector_hdmi_reset_tests,
2396 };
2397 
2398 /*
2399  * Test that the default behaviour for drm_hdmi_connector_mode_valid() is not
2400  * to reject any modes. Pass a correct EDID and verify that preferred mode
2401  * matches the expectations (1080p).
2402  */
2403 static void drm_test_check_mode_valid(struct kunit *test)
2404 {
2405 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2406 	struct drm_connector *conn;
2407 	struct drm_display_mode *preferred;
2408 
2409 	priv = drm_kunit_helper_connector_hdmi_init(test,
2410 						    BIT(HDMI_COLORSPACE_RGB),
2411 						    8);
2412 	KUNIT_ASSERT_NOT_NULL(test, priv);
2413 
2414 	conn = &priv->connector;
2415 	preferred = find_preferred_mode(conn);
2416 	KUNIT_ASSERT_NOT_NULL(test, preferred);
2417 
2418 	KUNIT_EXPECT_EQ(test, preferred->hdisplay, 1920);
2419 	KUNIT_EXPECT_EQ(test, preferred->vdisplay, 1080);
2420 	KUNIT_EXPECT_EQ(test, preferred->clock, 148500);
2421 }
2422 
2423 /*
2424  * Test that the drm_hdmi_connector_mode_valid() will reject modes depending on
2425  * the .tmds_char_rate_valid() behaviour.
2426  * Pass a correct EDID and verify that high-rate modes are filtered.
2427  */
2428 static void drm_test_check_mode_valid_reject_rate(struct kunit *test)
2429 {
2430 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2431 	struct drm_display_mode *preferred;
2432 
2433 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
2434 					BIT(HDMI_COLORSPACE_RGB),
2435 					8,
2436 					&reject_100mhz_connector_hdmi_funcs,
2437 					test_edid_hdmi_1080p_rgb_max_200mhz);
2438 	KUNIT_ASSERT_NOT_NULL(test, priv);
2439 
2440 	/*
2441 	 * Unlike the drm_test_check_mode_valid() here 1080p is rejected, but
2442 	 * 480p is allowed.
2443 	 */
2444 	preferred = find_preferred_mode(&priv->connector);
2445 	KUNIT_ASSERT_NOT_NULL(test, preferred);
2446 	KUNIT_EXPECT_EQ(test, preferred->hdisplay, 640);
2447 	KUNIT_EXPECT_EQ(test, preferred->vdisplay, 480);
2448 	KUNIT_EXPECT_EQ(test, preferred->clock, 25200);
2449 }
2450 
2451 /*
2452  * Test that the drm_hdmi_connector_mode_valid() will not mark any modes as
2453  * valid if .tmds_char_rate_valid() rejects all of them. Pass a correct EDID
2454  * and verify that there is no preferred mode and no modes were set for the
2455  * connector.
2456  */
2457 static void drm_test_check_mode_valid_reject(struct kunit *test)
2458 {
2459 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2460 	struct drm_connector *conn;
2461 	struct drm_display_mode *preferred;
2462 	unsigned char no_edid[] = {};
2463 	int ret;
2464 
2465 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
2466 					BIT(HDMI_COLORSPACE_RGB),
2467 					8,
2468 					&reject_connector_hdmi_funcs,
2469 					no_edid);
2470 	KUNIT_ASSERT_NOT_NULL(test, priv);
2471 
2472 	conn = &priv->connector;
2473 
2474 	/* should reject all modes */
2475 	ret = set_connector_edid(test, conn,
2476 				 test_edid_hdmi_1080p_rgb_max_200mhz,
2477 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz));
2478 	KUNIT_ASSERT_EQ(test, ret, 0);
2479 
2480 	preferred = find_preferred_mode(conn);
2481 	KUNIT_ASSERT_NULL(test, preferred);
2482 }
2483 
2484 /*
2485  * Test that the drm_hdmi_connector_mode_valid() will reject modes that don't
2486  * pass the info.max_tmds_clock filter. Pass crafted EDID and verify that
2487  * high-rate modes are filtered.
2488  */
2489 static void drm_test_check_mode_valid_reject_max_clock(struct kunit *test)
2490 {
2491 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2492 	struct drm_connector *conn;
2493 	struct drm_display_mode *preferred;
2494 
2495 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
2496 				BIT(HDMI_COLORSPACE_RGB),
2497 				8,
2498 				&dummy_connector_hdmi_funcs,
2499 				test_edid_hdmi_1080p_rgb_max_100mhz);
2500 	KUNIT_ASSERT_NOT_NULL(test, priv);
2501 
2502 	conn = &priv->connector;
2503 	KUNIT_ASSERT_EQ(test, conn->display_info.max_tmds_clock, 100 * 1000);
2504 
2505 	preferred = find_preferred_mode(conn);
2506 	KUNIT_ASSERT_NOT_NULL(test, preferred);
2507 	KUNIT_EXPECT_EQ(test, preferred->hdisplay, 640);
2508 	KUNIT_EXPECT_EQ(test, preferred->vdisplay, 480);
2509 	KUNIT_EXPECT_EQ(test, preferred->clock, 25200);
2510 }
2511 
2512 static struct kunit_case drm_atomic_helper_connector_hdmi_mode_valid_tests[] = {
2513 	KUNIT_CASE(drm_test_check_mode_valid),
2514 	KUNIT_CASE(drm_test_check_mode_valid_reject),
2515 	KUNIT_CASE(drm_test_check_mode_valid_reject_rate),
2516 	KUNIT_CASE(drm_test_check_mode_valid_reject_max_clock),
2517 	{ }
2518 };
2519 
2520 static struct kunit_suite drm_atomic_helper_connector_hdmi_mode_valid_test_suite = {
2521 	.name		= "drm_atomic_helper_connector_hdmi_mode_valid",
2522 	.test_cases	= drm_atomic_helper_connector_hdmi_mode_valid_tests,
2523 };
2524 
2525 /*
2526  * Test that the default behaviour works without errors. We expect that
2527  * infoframe-related hooks are called and there are no errors raised.
2528  */
2529 static void drm_test_check_infoframes(struct kunit *test)
2530 {
2531 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2532 	struct drm_modeset_acquire_ctx ctx;
2533 	struct drm_crtc_state *crtc_state;
2534 	struct drm_atomic_state *state;
2535 	struct drm_display_mode *preferred;
2536 	struct drm_connector *conn;
2537 	struct drm_device *drm;
2538 	struct drm_crtc *crtc;
2539 	int old_hdmi_update_failures;
2540 	int ret;
2541 
2542 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
2543 				BIT(HDMI_COLORSPACE_RGB),
2544 				8,
2545 				&dummy_connector_hdmi_funcs,
2546 				test_edid_hdmi_1080p_rgb_max_200mhz);
2547 	KUNIT_ASSERT_NOT_NULL(test, priv);
2548 
2549 	drm = &priv->drm;
2550 	crtc = priv->crtc;
2551 	conn = &priv->connector;
2552 
2553 	preferred = find_preferred_mode(conn);
2554 	KUNIT_ASSERT_NOT_NULL(test, preferred);
2555 
2556 	drm_modeset_acquire_init(&ctx, 0);
2557 
2558 retry_conn_enable:
2559 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
2560 						     crtc, conn,
2561 						     preferred,
2562 						     &ctx);
2563 	if (ret == -EDEADLK) {
2564 		ret = drm_modeset_backoff(&ctx);
2565 		if (!ret)
2566 			goto retry_conn_enable;
2567 	}
2568 	KUNIT_ASSERT_EQ(test, ret, 0);
2569 
2570 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
2571 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
2572 
2573 retry_crtc_state:
2574 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
2575 	if (PTR_ERR(crtc_state) == -EDEADLK) {
2576 		drm_atomic_state_clear(state);
2577 		ret = drm_modeset_backoff(&ctx);
2578 		if (!ret)
2579 			goto retry_crtc_state;
2580 	}
2581 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
2582 
2583 	crtc_state->mode_changed = true;
2584 
2585 	old_hdmi_update_failures = priv->hdmi_update_failures;
2586 
2587 	ret = drm_atomic_check_only(state);
2588 	if (ret == -EDEADLK) {
2589 		drm_atomic_state_clear(state);
2590 		ret = drm_modeset_backoff(&ctx);
2591 		if (!ret)
2592 			goto retry_crtc_state;
2593 	}
2594 	KUNIT_ASSERT_EQ(test, ret, 0);
2595 
2596 	ret = drm_atomic_commit(state);
2597 	if (ret == -EDEADLK) {
2598 		drm_atomic_state_clear(state);
2599 		ret = drm_modeset_backoff(&ctx);
2600 		if (!ret)
2601 			goto retry_crtc_state;
2602 	}
2603 	KUNIT_ASSERT_EQ(test, ret, 0);
2604 
2605 	KUNIT_EXPECT_GE(test, old_hdmi_update_failures, priv->hdmi_update_failures);
2606 
2607 	drm_modeset_drop_locks(&ctx);
2608 	drm_modeset_acquire_fini(&ctx);
2609 }
2610 
2611 static int reject_infoframe_write_infoframe(struct drm_connector *connector,
2612 					    const u8 *buffer, size_t len)
2613 {
2614 	return -EOPNOTSUPP;
2615 }
2616 
2617 static const struct drm_connector_hdmi_funcs reject_avi_infoframe_hdmi_funcs = {
2618 	.avi = {
2619 		.clear_infoframe = accept_infoframe_clear_infoframe,
2620 		.write_infoframe = reject_infoframe_write_infoframe,
2621 	},
2622 	.hdmi = {
2623 		.clear_infoframe = accept_infoframe_clear_infoframe,
2624 		.write_infoframe = accept_infoframe_write_infoframe,
2625 	},
2626 };
2627 
2628 /*
2629  * Test that the rejection of AVI InfoFrame results in the failure of
2630  * drm_atomic_helper_connector_hdmi_update_infoframes().
2631  */
2632 static void drm_test_check_reject_avi_infoframe(struct kunit *test)
2633 {
2634 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2635 	struct drm_modeset_acquire_ctx ctx;
2636 	struct drm_atomic_state *state;
2637 	struct drm_crtc_state *crtc_state;
2638 	struct drm_display_mode *preferred;
2639 	struct drm_connector *conn;
2640 	struct drm_device *drm;
2641 	struct drm_crtc *crtc;
2642 	int old_hdmi_update_failures;
2643 	int ret;
2644 
2645 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
2646 				BIT(HDMI_COLORSPACE_RGB),
2647 				8,
2648 				&reject_avi_infoframe_hdmi_funcs,
2649 				test_edid_hdmi_1080p_rgb_max_200mhz);
2650 	KUNIT_ASSERT_NOT_NULL(test, priv);
2651 
2652 	drm = &priv->drm;
2653 	crtc = priv->crtc;
2654 	conn = &priv->connector;
2655 
2656 	preferred = find_preferred_mode(conn);
2657 	KUNIT_ASSERT_NOT_NULL(test, preferred);
2658 
2659 	drm_modeset_acquire_init(&ctx, 0);
2660 
2661 retry_conn_enable:
2662 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
2663 						     crtc, conn,
2664 						     preferred,
2665 						     &ctx);
2666 	if (ret == -EDEADLK) {
2667 		ret = drm_modeset_backoff(&ctx);
2668 		if (!ret)
2669 			goto retry_conn_enable;
2670 	}
2671 	KUNIT_ASSERT_EQ(test, ret, 0);
2672 
2673 	drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs);
2674 
2675 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
2676 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
2677 
2678 retry_crtc_state:
2679 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
2680 	if (PTR_ERR(crtc_state) == -EDEADLK) {
2681 		drm_atomic_state_clear(state);
2682 		ret = drm_modeset_backoff(&ctx);
2683 		if (!ret)
2684 			goto retry_crtc_state;
2685 	}
2686 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
2687 
2688 	crtc_state->mode_changed = true;
2689 
2690 	old_hdmi_update_failures = priv->hdmi_update_failures;
2691 
2692 	ret = drm_atomic_check_only(state);
2693 	if (ret == -EDEADLK) {
2694 		drm_atomic_state_clear(state);
2695 		ret = drm_modeset_backoff(&ctx);
2696 		if (!ret)
2697 			goto retry_crtc_state;
2698 	}
2699 	KUNIT_ASSERT_EQ(test, ret, 0);
2700 
2701 	ret = drm_atomic_commit(state);
2702 	if (ret == -EDEADLK) {
2703 		drm_atomic_state_clear(state);
2704 		ret = drm_modeset_backoff(&ctx);
2705 		if (!ret)
2706 			goto retry_crtc_state;
2707 	}
2708 	KUNIT_ASSERT_EQ(test, ret, 0);
2709 
2710 	KUNIT_EXPECT_NE(test, old_hdmi_update_failures, priv->hdmi_update_failures);
2711 
2712 	drm_modeset_drop_locks(&ctx);
2713 	drm_modeset_acquire_fini(&ctx);
2714 }
2715 
2716 static const struct drm_connector_hdmi_funcs reject_hdr_infoframe_hdmi_funcs = {
2717 	.avi = {
2718 		.clear_infoframe = accept_infoframe_clear_infoframe,
2719 		.write_infoframe = accept_infoframe_write_infoframe,
2720 	},
2721 	.hdmi = {
2722 		.clear_infoframe = accept_infoframe_clear_infoframe,
2723 		.write_infoframe = accept_infoframe_write_infoframe,
2724 	},
2725 	.hdr_drm = {
2726 		.clear_infoframe = accept_infoframe_clear_infoframe,
2727 		.write_infoframe = reject_infoframe_write_infoframe,
2728 	},
2729 };
2730 
2731 /*
2732  * Test that the HDR InfoFrame isn't programmed in
2733  * drm_atomic_helper_connector_hdmi_update_infoframes() if the max_bpc is 8.
2734  */
2735 static void drm_test_check_reject_hdr_infoframe_bpc_8(struct kunit *test)
2736 {
2737 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2738 	struct drm_modeset_acquire_ctx ctx;
2739 	struct drm_atomic_state *state;
2740 	struct drm_connector_state *new_conn_state;
2741 	struct drm_crtc_state *crtc_state;
2742 	struct drm_display_mode *preferred;
2743 	struct drm_connector *conn;
2744 	struct drm_device *drm;
2745 	struct drm_crtc *crtc;
2746 	int old_hdmi_update_failures;
2747 	int ret;
2748 
2749 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
2750 				BIT(HDMI_COLORSPACE_RGB),
2751 				8,
2752 				&reject_hdr_infoframe_hdmi_funcs,
2753 				test_edid_hdmi_1080p_rgb_max_200mhz_hdr);
2754 	KUNIT_ASSERT_NOT_NULL(test, priv);
2755 
2756 	drm = &priv->drm;
2757 	crtc = priv->crtc;
2758 	conn = &priv->connector;
2759 
2760 	preferred = find_preferred_mode(conn);
2761 	KUNIT_ASSERT_NOT_NULL(test, preferred);
2762 
2763 	drm_modeset_acquire_init(&ctx, 0);
2764 
2765 retry_conn_enable:
2766 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
2767 						     crtc, conn,
2768 						     preferred,
2769 						     &ctx);
2770 	if (ret == -EDEADLK) {
2771 		ret = drm_modeset_backoff(&ctx);
2772 		if (!ret)
2773 			goto retry_conn_enable;
2774 	}
2775 	KUNIT_ASSERT_EQ(test, ret, 0);
2776 
2777 	drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs);
2778 
2779 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
2780 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
2781 
2782 retry_conn_state:
2783 	new_conn_state = drm_atomic_get_connector_state(state, conn);
2784 	if (PTR_ERR(new_conn_state) == -EDEADLK) {
2785 		drm_atomic_state_clear(state);
2786 		ret = drm_modeset_backoff(&ctx);
2787 		if (!ret)
2788 			goto retry_conn_state;
2789 	}
2790 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
2791 
2792 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
2793 	if (PTR_ERR(crtc_state) == -EDEADLK) {
2794 		drm_atomic_state_clear(state);
2795 		ret = drm_modeset_backoff(&ctx);
2796 		if (!ret)
2797 			goto retry_conn_state;
2798 	}
2799 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
2800 
2801 	/* Verify that there is no HDR property, so "userspace" can't set it. */
2802 	for (int i = 0; i < conn->base.properties->count; i++)
2803 		KUNIT_ASSERT_PTR_NE(test,
2804 				    drm->mode_config.hdr_output_metadata_property,
2805 				    conn->base.properties->properties[i]);
2806 
2807 	crtc_state->mode_changed = true;
2808 
2809 	old_hdmi_update_failures = priv->hdmi_update_failures;
2810 
2811 	ret = drm_atomic_check_only(state);
2812 	if (ret == -EDEADLK) {
2813 		drm_atomic_state_clear(state);
2814 		ret = drm_modeset_backoff(&ctx);
2815 		if (!ret)
2816 			goto retry_conn_state;
2817 	}
2818 	KUNIT_ASSERT_EQ(test, ret, 0);
2819 
2820 	ret = drm_atomic_commit(state);
2821 	if (ret == -EDEADLK) {
2822 		drm_atomic_state_clear(state);
2823 		ret = drm_modeset_backoff(&ctx);
2824 		if (!ret)
2825 			goto retry_conn_state;
2826 	}
2827 	KUNIT_ASSERT_EQ(test, ret, 0);
2828 
2829 	KUNIT_EXPECT_EQ(test, old_hdmi_update_failures, priv->hdmi_update_failures);
2830 
2831 	new_conn_state = conn->state;
2832 	KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
2833 
2834 	KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.output_bpc, 8);
2835 	KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.infoframes.hdr_drm.set, false);
2836 
2837 	drm_modeset_drop_locks(&ctx);
2838 	drm_modeset_acquire_fini(&ctx);
2839 }
2840 
2841 /*
2842  * Test that the rejection of HDR InfoFrame results in the failure of
2843  * drm_atomic_helper_connector_hdmi_update_infoframes() in the high bpc is
2844  * supported.
2845  */
2846 static void drm_test_check_reject_hdr_infoframe_bpc_10(struct kunit *test)
2847 {
2848 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2849 	struct drm_modeset_acquire_ctx ctx;
2850 	struct drm_atomic_state *state;
2851 	struct drm_connector_state *new_conn_state;
2852 	struct drm_crtc_state *crtc_state;
2853 	struct drm_display_mode *preferred;
2854 	struct drm_connector *conn;
2855 	struct drm_device *drm;
2856 	struct drm_crtc *crtc;
2857 	int old_hdmi_update_failures;
2858 	struct hdr_output_metadata hdr_data;
2859 	struct drm_property_blob *hdr_blob;
2860 	bool replaced;
2861 	int ret;
2862 
2863 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
2864 				BIT(HDMI_COLORSPACE_RGB),
2865 				10,
2866 				&reject_hdr_infoframe_hdmi_funcs,
2867 				test_edid_hdmi_1080p_rgb_max_200mhz_hdr);
2868 	KUNIT_ASSERT_NOT_NULL(test, priv);
2869 
2870 	drm = &priv->drm;
2871 	crtc = priv->crtc;
2872 	conn = &priv->connector;
2873 
2874 	preferred = find_preferred_mode(conn);
2875 	KUNIT_ASSERT_NOT_NULL(test, preferred);
2876 
2877 	drm_modeset_acquire_init(&ctx, 0);
2878 
2879 retry_conn_enable:
2880 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
2881 						     crtc, conn,
2882 						     preferred,
2883 						     &ctx);
2884 	if (ret == -EDEADLK) {
2885 		ret = drm_modeset_backoff(&ctx);
2886 		if (!ret)
2887 			goto retry_conn_enable;
2888 	}
2889 	KUNIT_ASSERT_EQ(test, ret, 0);
2890 
2891 	drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs);
2892 
2893 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
2894 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
2895 
2896 retry_conn_state:
2897 	new_conn_state = drm_atomic_get_connector_state(state, conn);
2898 	if (PTR_ERR(new_conn_state) == -EDEADLK) {
2899 		drm_atomic_state_clear(state);
2900 		ret = drm_modeset_backoff(&ctx);
2901 		if (!ret)
2902 			goto retry_conn_state;
2903 	}
2904 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
2905 
2906 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
2907 	if (PTR_ERR(crtc_state) == -EDEADLK) {
2908 		drm_atomic_state_clear(state);
2909 		ret = drm_modeset_backoff(&ctx);
2910 		if (!ret)
2911 			goto retry_conn_state;
2912 	}
2913 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
2914 
2915 	hdr_data.metadata_type = HDMI_STATIC_METADATA_TYPE1;
2916 	hdr_data.hdmi_metadata_type1.eotf = HDMI_EOTF_TRADITIONAL_GAMMA_SDR;
2917 	hdr_data.hdmi_metadata_type1.metadata_type = HDMI_STATIC_METADATA_TYPE1;
2918 
2919 	hdr_blob = drm_property_create_blob(drm, sizeof(hdr_data), &hdr_data);
2920 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hdr_blob);
2921 
2922 	ret = drm_property_replace_blob_from_id(drm,
2923 						&new_conn_state->hdr_output_metadata,
2924 						hdr_blob->base.id,
2925 						-1, sizeof(struct hdr_output_metadata), -1,
2926 						&replaced);
2927 	KUNIT_ASSERT_EQ(test, ret, 0);
2928 	KUNIT_ASSERT_EQ(test, replaced, true);
2929 
2930 	crtc_state->mode_changed = true;
2931 
2932 	old_hdmi_update_failures = priv->hdmi_update_failures;
2933 
2934 	ret = drm_atomic_check_only(state);
2935 	if (ret == -EDEADLK) {
2936 		drm_atomic_state_clear(state);
2937 		ret = drm_modeset_backoff(&ctx);
2938 		if (!ret)
2939 			goto retry_conn_state;
2940 	}
2941 	KUNIT_ASSERT_EQ(test, ret, 0);
2942 
2943 	ret = drm_atomic_commit(state);
2944 	if (ret == -EDEADLK) {
2945 		drm_atomic_state_clear(state);
2946 		ret = drm_modeset_backoff(&ctx);
2947 		if (!ret)
2948 			goto retry_conn_state;
2949 	}
2950 	KUNIT_ASSERT_EQ(test, ret, 0);
2951 
2952 	KUNIT_EXPECT_LE(test, old_hdmi_update_failures, priv->hdmi_update_failures);
2953 
2954 	new_conn_state = conn->state;
2955 	KUNIT_ASSERT_NOT_NULL(test, new_conn_state);
2956 
2957 	KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.output_bpc, 10);
2958 	KUNIT_ASSERT_EQ(test, new_conn_state->hdmi.infoframes.hdr_drm.set, true);
2959 
2960 	drm_modeset_drop_locks(&ctx);
2961 	drm_modeset_acquire_fini(&ctx);
2962 }
2963 
2964 static const struct drm_connector_hdmi_funcs reject_audio_infoframe_hdmi_funcs = {
2965 	.avi = {
2966 		.clear_infoframe = accept_infoframe_clear_infoframe,
2967 		.write_infoframe = accept_infoframe_write_infoframe,
2968 	},
2969 	.hdmi = {
2970 		.clear_infoframe = accept_infoframe_clear_infoframe,
2971 		.write_infoframe = accept_infoframe_write_infoframe,
2972 	},
2973 	.audio = {
2974 		.clear_infoframe = accept_infoframe_clear_infoframe,
2975 		.write_infoframe = reject_infoframe_write_infoframe,
2976 	},
2977 };
2978 
2979 /*
2980  * Test that Audio InfoFrame is only programmed if we call a corresponding API,
2981  * thus the drivers can safely assume that they won't get Audio InfoFrames if
2982  * they don't call it.
2983  */
2984 static void drm_test_check_reject_audio_infoframe(struct kunit *test)
2985 {
2986 	struct drm_atomic_helper_connector_hdmi_priv *priv;
2987 	struct drm_modeset_acquire_ctx ctx;
2988 	struct drm_atomic_state *state;
2989 	struct drm_crtc_state *crtc_state;
2990 	struct drm_display_mode *preferred;
2991 	struct drm_connector *conn;
2992 	struct drm_device *drm;
2993 	struct drm_crtc *crtc;
2994 	int old_hdmi_update_failures;
2995 	struct hdmi_audio_infoframe cea;
2996 	int ret;
2997 
2998 	priv = drm_kunit_helper_connector_hdmi_init_with_edid_funcs(test,
2999 				BIT(HDMI_COLORSPACE_RGB),
3000 				8,
3001 				&reject_audio_infoframe_hdmi_funcs,
3002 				test_edid_hdmi_1080p_rgb_max_200mhz);
3003 	KUNIT_ASSERT_NOT_NULL(test, priv);
3004 
3005 	drm = &priv->drm;
3006 	crtc = priv->crtc;
3007 	conn = &priv->connector;
3008 
3009 	preferred = find_preferred_mode(conn);
3010 	KUNIT_ASSERT_NOT_NULL(test, preferred);
3011 
3012 	drm_modeset_acquire_init(&ctx, 0);
3013 
3014 retry_conn_enable:
3015 	ret = drm_kunit_helper_enable_crtc_connector(test, drm,
3016 						     crtc, conn,
3017 						     preferred,
3018 						     &ctx);
3019 	if (ret == -EDEADLK) {
3020 		ret = drm_modeset_backoff(&ctx);
3021 		if (!ret)
3022 			goto retry_conn_enable;
3023 	}
3024 	KUNIT_ASSERT_EQ(test, ret, 0);
3025 
3026 	drm_encoder_helper_add(&priv->encoder, &test_encoder_helper_funcs);
3027 
3028 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
3029 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
3030 
3031 retry_crtc_state:
3032 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
3033 	if (PTR_ERR(crtc_state) == -EDEADLK) {
3034 		drm_atomic_state_clear(state);
3035 		ret = drm_modeset_backoff(&ctx);
3036 		if (!ret)
3037 			goto retry_crtc_state;
3038 	}
3039 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
3040 
3041 	crtc_state->mode_changed = true;
3042 
3043 	old_hdmi_update_failures = priv->hdmi_update_failures;
3044 
3045 	ret = drm_atomic_check_only(state);
3046 	if (ret == -EDEADLK) {
3047 		drm_atomic_state_clear(state);
3048 		ret = drm_modeset_backoff(&ctx);
3049 		if (!ret)
3050 			goto retry_crtc_state;
3051 	}
3052 	KUNIT_ASSERT_EQ(test, ret, 0);
3053 
3054 	ret = drm_atomic_commit(state);
3055 	if (ret == -EDEADLK) {
3056 		drm_atomic_state_clear(state);
3057 		ret = drm_modeset_backoff(&ctx);
3058 		if (!ret)
3059 			goto retry_crtc_state;
3060 	}
3061 	KUNIT_ASSERT_EQ(test, ret, 0);
3062 
3063 	KUNIT_EXPECT_EQ(test, old_hdmi_update_failures, priv->hdmi_update_failures);
3064 
3065 	/*
3066 	 * So, it works without Audio InfoFrame, let's fail with it in place,
3067 	 * checking that writing the infofraem actually gets triggered.
3068 	 */
3069 
3070 	hdmi_audio_infoframe_init(&cea);
3071 	cea.channels = 2;
3072 	cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
3073 	cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
3074 	cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
3075 
3076 	ret = drm_atomic_helper_connector_hdmi_update_audio_infoframe(conn, &cea);
3077 	KUNIT_ASSERT_EQ(test, ret, -EOPNOTSUPP);
3078 
3079 	state = drm_kunit_helper_atomic_state_alloc(test, drm, &ctx);
3080 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
3081 
3082 retry_crtc_state_2:
3083 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
3084 	if (PTR_ERR(crtc_state) == -EDEADLK) {
3085 		drm_atomic_state_clear(state);
3086 		ret = drm_modeset_backoff(&ctx);
3087 		if (!ret)
3088 			goto retry_crtc_state_2;
3089 	}
3090 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
3091 
3092 	crtc_state->mode_changed = true;
3093 
3094 	old_hdmi_update_failures = priv->hdmi_update_failures;
3095 
3096 	ret = drm_atomic_check_only(state);
3097 	if (ret == -EDEADLK) {
3098 		drm_atomic_state_clear(state);
3099 		ret = drm_modeset_backoff(&ctx);
3100 		if (!ret)
3101 			goto retry_crtc_state_2;
3102 	}
3103 	KUNIT_ASSERT_EQ(test, ret, 0);
3104 
3105 	ret = drm_atomic_commit(state);
3106 	if (ret == -EDEADLK) {
3107 		drm_atomic_state_clear(state);
3108 		ret = drm_modeset_backoff(&ctx);
3109 		if (!ret)
3110 			goto retry_crtc_state_2;
3111 	}
3112 	KUNIT_ASSERT_EQ(test, ret, 0);
3113 
3114 	KUNIT_EXPECT_LE(test, old_hdmi_update_failures, priv->hdmi_update_failures);
3115 
3116 	drm_modeset_drop_locks(&ctx);
3117 	drm_modeset_acquire_fini(&ctx);
3118 }
3119 
3120 
3121 static struct kunit_case drm_atomic_helper_connector_hdmi_infoframes_tests[] = {
3122 	KUNIT_CASE(drm_test_check_infoframes),
3123 	KUNIT_CASE(drm_test_check_reject_avi_infoframe),
3124 	KUNIT_CASE(drm_test_check_reject_hdr_infoframe_bpc_8),
3125 	KUNIT_CASE(drm_test_check_reject_hdr_infoframe_bpc_10),
3126 	KUNIT_CASE(drm_test_check_reject_audio_infoframe),
3127 	{ }
3128 };
3129 
3130 static struct kunit_suite drm_atomic_helper_connector_hdmi_infoframes_test_suite = {
3131 	.name		= "drm_atomic_helper_connector_hdmi_infoframes",
3132 	.test_cases	= drm_atomic_helper_connector_hdmi_infoframes_tests,
3133 };
3134 
3135 kunit_test_suites(
3136 	&drm_atomic_helper_connector_hdmi_check_test_suite,
3137 	&drm_atomic_helper_connector_hdmi_reset_test_suite,
3138 	&drm_atomic_helper_connector_hdmi_mode_valid_test_suite,
3139 	&drm_atomic_helper_connector_hdmi_infoframes_test_suite,
3140 );
3141 
3142 MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>");
3143 MODULE_DESCRIPTION("Kunit test for drm_hdmi_state_helper functions");
3144 MODULE_LICENSE("GPL");
3145