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