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