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