• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
dummy_connector_get_modes(struct drm_connector * connector)134 static int dummy_connector_get_modes(struct drm_connector *connector)
135 {
136 	struct drm_atomic_helper_connector_hdmi_priv *priv =
137 		connector_to_priv(connector);
138 	const struct drm_edid *edid;
139 	unsigned int num_modes;
140 
141 	edid = drm_edid_alloc(priv->current_edid, priv->current_edid_len);
142 	if (!edid)
143 		return -EINVAL;
144 
145 	drm_edid_connector_update(connector, edid);
146 	num_modes = drm_edid_connector_add_modes(connector);
147 
148 	drm_edid_free(edid);
149 
150 	return num_modes;
151 }
152 
153 static const struct drm_connector_helper_funcs dummy_connector_helper_funcs = {
154 	.atomic_check	= drm_atomic_helper_connector_hdmi_check,
155 	.get_modes	= dummy_connector_get_modes,
156 };
157 
dummy_hdmi_connector_reset(struct drm_connector * connector)158 static void dummy_hdmi_connector_reset(struct drm_connector *connector)
159 {
160 	drm_atomic_helper_connector_reset(connector);
161 	__drm_atomic_helper_connector_hdmi_reset(connector, connector->state);
162 }
163 
164 static const struct drm_connector_funcs dummy_connector_funcs = {
165 	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
166 	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
167 	.fill_modes		= drm_helper_probe_single_connector_modes,
168 	.reset			= dummy_hdmi_connector_reset,
169 };
170 
171 static
172 struct drm_atomic_helper_connector_hdmi_priv *
drm_atomic_helper_connector_hdmi_init(struct kunit * test,unsigned int formats,unsigned int max_bpc)173 drm_atomic_helper_connector_hdmi_init(struct kunit *test,
174 				      unsigned int formats,
175 				      unsigned int max_bpc)
176 {
177 	struct drm_atomic_helper_connector_hdmi_priv *priv;
178 	struct drm_connector *conn;
179 	struct drm_encoder *enc;
180 	struct drm_device *drm;
181 	struct device *dev;
182 	int ret;
183 
184 	dev = drm_kunit_helper_alloc_device(test);
185 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
186 
187 	priv = drm_kunit_helper_alloc_drm_device(test, dev,
188 						 struct drm_atomic_helper_connector_hdmi_priv, drm,
189 						 DRIVER_MODESET | DRIVER_ATOMIC);
190 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
191 	test->priv = priv;
192 
193 	drm = &priv->drm;
194 	priv->plane = drm_kunit_helper_create_primary_plane(test, drm,
195 							    NULL,
196 							    NULL,
197 							    NULL, 0,
198 							    NULL);
199 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->plane);
200 
201 	priv->crtc = drm_kunit_helper_create_crtc(test, drm,
202 						  priv->plane, NULL,
203 						  NULL,
204 						  NULL);
205 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->crtc);
206 
207 	enc = &priv->encoder;
208 	ret = drmm_encoder_init(drm, enc, NULL, DRM_MODE_ENCODER_TMDS, NULL);
209 	KUNIT_ASSERT_EQ(test, ret, 0);
210 
211 	enc->possible_crtcs = drm_crtc_mask(priv->crtc);
212 
213 	conn = &priv->connector;
214 	ret = drmm_connector_hdmi_init(drm, conn,
215 				       "Vendor", "Product",
216 				       &dummy_connector_funcs,
217 				       &dummy_connector_hdmi_funcs,
218 				       DRM_MODE_CONNECTOR_HDMIA,
219 				       NULL,
220 				       formats,
221 				       max_bpc);
222 	KUNIT_ASSERT_EQ(test, ret, 0);
223 
224 	drm_connector_helper_add(conn, &dummy_connector_helper_funcs);
225 	drm_connector_attach_encoder(conn, enc);
226 
227 	drm_mode_config_reset(drm);
228 
229 	ret = set_connector_edid(test, conn,
230 				 test_edid_hdmi_1080p_rgb_max_200mhz,
231 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz));
232 	KUNIT_ASSERT_GT(test, ret, 0);
233 
234 	return priv;
235 }
236 
237 /*
238  * Test that if we change the RGB quantization property to a different
239  * value, we trigger a mode change on the connector's CRTC, which will
240  * in turn disable/enable the connector.
241  */
drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit * test)242 static void drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit *test)
243 {
244 	struct drm_atomic_helper_connector_hdmi_priv *priv;
245 	struct drm_modeset_acquire_ctx *ctx;
246 	struct drm_connector_state *old_conn_state;
247 	struct drm_connector_state *new_conn_state;
248 	struct drm_crtc_state *crtc_state;
249 	struct drm_atomic_state *state;
250 	struct drm_display_mode *preferred;
251 	struct drm_connector *conn;
252 	struct drm_device *drm;
253 	struct drm_crtc *crtc;
254 	int ret;
255 
256 	priv = drm_atomic_helper_connector_hdmi_init(test,
257 						     BIT(HDMI_COLORSPACE_RGB),
258 						     8);
259 	KUNIT_ASSERT_NOT_NULL(test, priv);
260 
261 	drm = &priv->drm;
262 	crtc = priv->crtc;
263 	conn = &priv->connector;
264 
265 	preferred = find_preferred_mode(conn);
266 	KUNIT_ASSERT_NOT_NULL(test, preferred);
267 
268 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
269 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
270 
271 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
272 	KUNIT_ASSERT_EQ(test, ret, 0);
273 
274 	state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
275 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
276 
277 	new_conn_state = drm_atomic_get_connector_state(state, conn);
278 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
279 
280 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
281 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
282 
283 	new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
284 
285 	KUNIT_ASSERT_NE(test,
286 			old_conn_state->hdmi.broadcast_rgb,
287 			new_conn_state->hdmi.broadcast_rgb);
288 
289 	ret = drm_atomic_check_only(state);
290 	KUNIT_ASSERT_EQ(test, ret, 0);
291 
292 	new_conn_state = drm_atomic_get_new_connector_state(state, conn);
293 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
294 	KUNIT_EXPECT_EQ(test, new_conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_FULL);
295 
296 	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
297 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
298 	KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed);
299 }
300 
301 /*
302  * Test that if we set the RGB quantization property to the same value,
303  * we don't trigger a mode change on the connector's CRTC and leave the
304  * connector unaffected.
305  */
drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit * test)306 static void drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *test)
307 {
308 	struct drm_atomic_helper_connector_hdmi_priv *priv;
309 	struct drm_modeset_acquire_ctx *ctx;
310 	struct drm_connector_state *old_conn_state;
311 	struct drm_connector_state *new_conn_state;
312 	struct drm_crtc_state *crtc_state;
313 	struct drm_atomic_state *state;
314 	struct drm_display_mode *preferred;
315 	struct drm_connector *conn;
316 	struct drm_device *drm;
317 	struct drm_crtc *crtc;
318 	int ret;
319 
320 	priv = drm_atomic_helper_connector_hdmi_init(test,
321 						     BIT(HDMI_COLORSPACE_RGB),
322 						     8);
323 	KUNIT_ASSERT_NOT_NULL(test, priv);
324 
325 	drm = &priv->drm;
326 	crtc = priv->crtc;
327 	conn = &priv->connector;
328 
329 	preferred = find_preferred_mode(conn);
330 	KUNIT_ASSERT_NOT_NULL(test, preferred);
331 
332 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
333 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
334 
335 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
336 	KUNIT_ASSERT_EQ(test, ret, 0);
337 
338 	state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
339 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
340 
341 	new_conn_state = drm_atomic_get_connector_state(state, conn);
342 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
343 
344 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
345 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
346 
347 	new_conn_state->hdmi.broadcast_rgb = old_conn_state->hdmi.broadcast_rgb;
348 
349 	ret = drm_atomic_check_only(state);
350 	KUNIT_ASSERT_EQ(test, ret, 0);
351 
352 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
353 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
354 
355 	new_conn_state = drm_atomic_get_new_connector_state(state, conn);
356 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
357 
358 	KUNIT_EXPECT_EQ(test,
359 			old_conn_state->hdmi.broadcast_rgb,
360 			new_conn_state->hdmi.broadcast_rgb);
361 
362 	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
363 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
364 	KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed);
365 }
366 
367 /*
368  * Test that for an HDMI connector, with an HDMI monitor, if the
369  * Broadcast RGB property is set to auto with a mode that isn't the
370  * VIC-1 mode, we will get a limited RGB Quantization Range.
371  */
drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit * test)372 static void drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit *test)
373 {
374 	struct drm_atomic_helper_connector_hdmi_priv *priv;
375 	struct drm_modeset_acquire_ctx *ctx;
376 	struct drm_connector_state *conn_state;
377 	struct drm_atomic_state *state;
378 	struct drm_display_mode *preferred;
379 	struct drm_connector *conn;
380 	struct drm_device *drm;
381 	struct drm_crtc *crtc;
382 	int ret;
383 
384 	priv = drm_atomic_helper_connector_hdmi_init(test,
385 						     BIT(HDMI_COLORSPACE_RGB),
386 						     8);
387 	KUNIT_ASSERT_NOT_NULL(test, priv);
388 
389 	drm = &priv->drm;
390 	crtc = priv->crtc;
391 	conn = &priv->connector;
392 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
393 
394 	preferred = find_preferred_mode(conn);
395 	KUNIT_ASSERT_NOT_NULL(test, preferred);
396 	KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
397 
398 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
399 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
400 
401 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
402 	KUNIT_ASSERT_EQ(test, ret, 0);
403 
404 	state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
405 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
406 
407 	conn_state = drm_atomic_get_connector_state(state, conn);
408 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
409 
410 	KUNIT_ASSERT_EQ(test,
411 			conn_state->hdmi.broadcast_rgb,
412 			DRM_HDMI_BROADCAST_RGB_AUTO);
413 
414 	ret = drm_atomic_check_only(state);
415 	KUNIT_ASSERT_EQ(test, ret, 0);
416 
417 	conn_state = drm_atomic_get_connector_state(state, conn);
418 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
419 
420 	KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
421 }
422 
423 /*
424  * Test that for an HDMI connector, with an HDMI monitor, if the
425  * Broadcast RGB property is set to auto with a VIC-1 mode, we will get
426  * a full RGB Quantization Range.
427  */
drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit * test)428 static void drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit *test)
429 {
430 	struct drm_atomic_helper_connector_hdmi_priv *priv;
431 	struct drm_modeset_acquire_ctx *ctx;
432 	struct drm_connector_state *conn_state;
433 	struct drm_atomic_state *state;
434 	struct drm_display_mode *mode;
435 	struct drm_connector *conn;
436 	struct drm_device *drm;
437 	struct drm_crtc *crtc;
438 	int ret;
439 
440 	priv = drm_atomic_helper_connector_hdmi_init(test,
441 						     BIT(HDMI_COLORSPACE_RGB),
442 						     8);
443 	KUNIT_ASSERT_NOT_NULL(test, priv);
444 
445 	drm = &priv->drm;
446 	conn = &priv->connector;
447 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
448 
449 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
450 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
451 
452 	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
453 	KUNIT_ASSERT_NOT_NULL(test, mode);
454 
455 	crtc = priv->crtc;
456 	ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
457 	KUNIT_ASSERT_EQ(test, ret, 0);
458 
459 	state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
460 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
461 
462 	conn_state = drm_atomic_get_connector_state(state, conn);
463 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
464 
465 	KUNIT_ASSERT_EQ(test,
466 			conn_state->hdmi.broadcast_rgb,
467 			DRM_HDMI_BROADCAST_RGB_AUTO);
468 
469 	ret = drm_atomic_check_only(state);
470 	KUNIT_ASSERT_EQ(test, ret, 0);
471 
472 	conn_state = drm_atomic_get_connector_state(state, conn);
473 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
474 
475 	KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range);
476 }
477 
478 /*
479  * Test that for an HDMI connector, with an HDMI monitor, if the
480  * Broadcast RGB property is set to full with a mode that isn't the
481  * VIC-1 mode, we will get a full RGB Quantization Range.
482  */
drm_test_check_broadcast_rgb_full_cea_mode(struct kunit * test)483 static void drm_test_check_broadcast_rgb_full_cea_mode(struct kunit *test)
484 {
485 	struct drm_atomic_helper_connector_hdmi_priv *priv;
486 	struct drm_modeset_acquire_ctx *ctx;
487 	struct drm_connector_state *conn_state;
488 	struct drm_atomic_state *state;
489 	struct drm_display_mode *preferred;
490 	struct drm_connector *conn;
491 	struct drm_device *drm;
492 	struct drm_crtc *crtc;
493 	int ret;
494 
495 	priv = drm_atomic_helper_connector_hdmi_init(test,
496 						     BIT(HDMI_COLORSPACE_RGB),
497 						     8);
498 	KUNIT_ASSERT_NOT_NULL(test, priv);
499 
500 	drm = &priv->drm;
501 	crtc = priv->crtc;
502 	conn = &priv->connector;
503 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
504 
505 	preferred = find_preferred_mode(conn);
506 	KUNIT_ASSERT_NOT_NULL(test, preferred);
507 	KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
508 
509 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
510 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
511 
512 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
513 	KUNIT_ASSERT_EQ(test, ret, 0);
514 
515 	state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
516 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
517 
518 	conn_state = drm_atomic_get_connector_state(state, conn);
519 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
520 
521 	conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
522 
523 	ret = drm_atomic_check_only(state);
524 	KUNIT_ASSERT_EQ(test, ret, 0);
525 
526 	conn_state = drm_atomic_get_connector_state(state, conn);
527 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
528 
529 	KUNIT_ASSERT_EQ(test,
530 			conn_state->hdmi.broadcast_rgb,
531 			DRM_HDMI_BROADCAST_RGB_FULL);
532 
533 	KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range);
534 }
535 
536 /*
537  * Test that for an HDMI connector, with an HDMI monitor, if the
538  * Broadcast RGB property is set to full with a VIC-1 mode, we will get
539  * a full RGB Quantization Range.
540  */
drm_test_check_broadcast_rgb_full_cea_mode_vic_1(struct kunit * test)541 static void drm_test_check_broadcast_rgb_full_cea_mode_vic_1(struct kunit *test)
542 {
543 	struct drm_atomic_helper_connector_hdmi_priv *priv;
544 	struct drm_modeset_acquire_ctx *ctx;
545 	struct drm_connector_state *conn_state;
546 	struct drm_atomic_state *state;
547 	struct drm_display_mode *mode;
548 	struct drm_connector *conn;
549 	struct drm_device *drm;
550 	struct drm_crtc *crtc;
551 	int ret;
552 
553 	priv = drm_atomic_helper_connector_hdmi_init(test,
554 						     BIT(HDMI_COLORSPACE_RGB),
555 						     8);
556 	KUNIT_ASSERT_NOT_NULL(test, priv);
557 
558 	drm = &priv->drm;
559 	conn = &priv->connector;
560 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
561 
562 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
563 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
564 
565 	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
566 	KUNIT_ASSERT_NOT_NULL(test, mode);
567 
568 	crtc = priv->crtc;
569 	ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
570 	KUNIT_ASSERT_EQ(test, ret, 0);
571 
572 	state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
573 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
574 
575 	conn_state = drm_atomic_get_connector_state(state, conn);
576 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
577 
578 	conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
579 
580 	ret = drm_atomic_check_only(state);
581 	KUNIT_ASSERT_EQ(test, ret, 0);
582 
583 	conn_state = drm_atomic_get_connector_state(state, conn);
584 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
585 
586 	KUNIT_ASSERT_EQ(test,
587 			conn_state->hdmi.broadcast_rgb,
588 			DRM_HDMI_BROADCAST_RGB_FULL);
589 
590 	KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range);
591 }
592 
593 /*
594  * Test that for an HDMI connector, with an HDMI monitor, if the
595  * Broadcast RGB property is set to limited with a mode that isn't the
596  * VIC-1 mode, we will get a limited RGB Quantization Range.
597  */
drm_test_check_broadcast_rgb_limited_cea_mode(struct kunit * test)598 static void drm_test_check_broadcast_rgb_limited_cea_mode(struct kunit *test)
599 {
600 	struct drm_atomic_helper_connector_hdmi_priv *priv;
601 	struct drm_modeset_acquire_ctx *ctx;
602 	struct drm_connector_state *conn_state;
603 	struct drm_atomic_state *state;
604 	struct drm_display_mode *preferred;
605 	struct drm_connector *conn;
606 	struct drm_device *drm;
607 	struct drm_crtc *crtc;
608 	int ret;
609 
610 	priv = drm_atomic_helper_connector_hdmi_init(test,
611 						     BIT(HDMI_COLORSPACE_RGB),
612 						     8);
613 	KUNIT_ASSERT_NOT_NULL(test, priv);
614 
615 	drm = &priv->drm;
616 	crtc = priv->crtc;
617 	conn = &priv->connector;
618 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
619 
620 	preferred = find_preferred_mode(conn);
621 	KUNIT_ASSERT_NOT_NULL(test, preferred);
622 	KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
623 
624 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
625 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
626 
627 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
628 	KUNIT_ASSERT_EQ(test, ret, 0);
629 
630 	state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
631 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
632 
633 	conn_state = drm_atomic_get_connector_state(state, conn);
634 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
635 
636 	conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED;
637 
638 	ret = drm_atomic_check_only(state);
639 	KUNIT_ASSERT_EQ(test, ret, 0);
640 
641 	conn_state = drm_atomic_get_connector_state(state, conn);
642 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
643 
644 	KUNIT_ASSERT_EQ(test,
645 			conn_state->hdmi.broadcast_rgb,
646 			DRM_HDMI_BROADCAST_RGB_LIMITED);
647 
648 	KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
649 }
650 
651 /*
652  * Test that for an HDMI connector, with an HDMI monitor, if the
653  * Broadcast RGB property is set to limited with a VIC-1 mode, we will
654  * get a limited RGB Quantization Range.
655  */
drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit * test)656 static void drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit *test)
657 {
658 	struct drm_atomic_helper_connector_hdmi_priv *priv;
659 	struct drm_modeset_acquire_ctx *ctx;
660 	struct drm_connector_state *conn_state;
661 	struct drm_atomic_state *state;
662 	struct drm_display_mode *mode;
663 	struct drm_connector *conn;
664 	struct drm_device *drm;
665 	struct drm_crtc *crtc;
666 	int ret;
667 
668 	priv = drm_atomic_helper_connector_hdmi_init(test,
669 						     BIT(HDMI_COLORSPACE_RGB),
670 						     8);
671 	KUNIT_ASSERT_NOT_NULL(test, priv);
672 
673 	drm = &priv->drm;
674 	conn = &priv->connector;
675 	KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
676 
677 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
678 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
679 
680 	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
681 	KUNIT_ASSERT_NOT_NULL(test, mode);
682 
683 	crtc = priv->crtc;
684 	ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
685 	KUNIT_ASSERT_EQ(test, ret, 0);
686 
687 	state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
688 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
689 
690 	conn_state = drm_atomic_get_connector_state(state, conn);
691 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
692 
693 	conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED;
694 
695 	ret = drm_atomic_check_only(state);
696 	KUNIT_ASSERT_EQ(test, ret, 0);
697 
698 	conn_state = drm_atomic_get_connector_state(state, conn);
699 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
700 
701 	KUNIT_ASSERT_EQ(test,
702 			conn_state->hdmi.broadcast_rgb,
703 			DRM_HDMI_BROADCAST_RGB_LIMITED);
704 
705 	KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
706 }
707 
708 /*
709  * Test that if we change the maximum bpc property to a different value,
710  * we trigger a mode change on the connector's CRTC, which will in turn
711  * disable/enable the connector.
712  */
drm_test_check_output_bpc_crtc_mode_changed(struct kunit * test)713 static void drm_test_check_output_bpc_crtc_mode_changed(struct kunit *test)
714 {
715 	struct drm_atomic_helper_connector_hdmi_priv *priv;
716 	struct drm_modeset_acquire_ctx *ctx;
717 	struct drm_connector_state *old_conn_state;
718 	struct drm_connector_state *new_conn_state;
719 	struct drm_crtc_state *crtc_state;
720 	struct drm_atomic_state *state;
721 	struct drm_display_mode *preferred;
722 	struct drm_connector *conn;
723 	struct drm_device *drm;
724 	struct drm_crtc *crtc;
725 	int ret;
726 
727 	priv = drm_atomic_helper_connector_hdmi_init(test,
728 						     BIT(HDMI_COLORSPACE_RGB),
729 						     10);
730 	KUNIT_ASSERT_NOT_NULL(test, priv);
731 
732 	drm = &priv->drm;
733 	crtc = priv->crtc;
734 	conn = &priv->connector;
735 	ret = set_connector_edid(test, conn,
736 				 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
737 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
738 	KUNIT_ASSERT_GT(test, ret, 0);
739 
740 	preferred = find_preferred_mode(conn);
741 	KUNIT_ASSERT_NOT_NULL(test, preferred);
742 
743 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
744 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
745 
746 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
747 	KUNIT_ASSERT_EQ(test, ret, 0);
748 
749 	state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
750 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
751 
752 	new_conn_state = drm_atomic_get_connector_state(state, conn);
753 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
754 
755 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
756 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
757 
758 	new_conn_state->max_requested_bpc = 8;
759 
760 	KUNIT_ASSERT_NE(test,
761 			old_conn_state->max_requested_bpc,
762 			new_conn_state->max_requested_bpc);
763 
764 	ret = drm_atomic_check_only(state);
765 	KUNIT_ASSERT_EQ(test, ret, 0);
766 
767 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
768 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
769 
770 	new_conn_state = drm_atomic_get_new_connector_state(state, conn);
771 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
772 
773 	KUNIT_ASSERT_NE(test,
774 			old_conn_state->hdmi.output_bpc,
775 			new_conn_state->hdmi.output_bpc);
776 
777 	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
778 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
779 	KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed);
780 }
781 
782 /*
783  * Test that if we set the output bpc property to the same value, we
784  * don't trigger a mode change on the connector's CRTC and leave the
785  * connector unaffected.
786  */
drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit * test)787 static void drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test)
788 {
789 	struct drm_atomic_helper_connector_hdmi_priv *priv;
790 	struct drm_modeset_acquire_ctx *ctx;
791 	struct drm_connector_state *old_conn_state;
792 	struct drm_connector_state *new_conn_state;
793 	struct drm_crtc_state *crtc_state;
794 	struct drm_atomic_state *state;
795 	struct drm_display_mode *preferred;
796 	struct drm_connector *conn;
797 	struct drm_device *drm;
798 	struct drm_crtc *crtc;
799 	int ret;
800 
801 	priv = drm_atomic_helper_connector_hdmi_init(test,
802 						     BIT(HDMI_COLORSPACE_RGB),
803 						     10);
804 	KUNIT_ASSERT_NOT_NULL(test, priv);
805 
806 	drm = &priv->drm;
807 	crtc = priv->crtc;
808 	conn = &priv->connector;
809 	ret = set_connector_edid(test, conn,
810 				 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
811 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
812 	KUNIT_ASSERT_GT(test, ret, 0);
813 
814 	preferred = find_preferred_mode(conn);
815 	KUNIT_ASSERT_NOT_NULL(test, preferred);
816 
817 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
818 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
819 
820 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
821 	KUNIT_ASSERT_EQ(test, ret, 0);
822 
823 	state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
824 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
825 
826 	new_conn_state = drm_atomic_get_connector_state(state, conn);
827 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
828 
829 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
830 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
831 
832 	KUNIT_ASSERT_EQ(test,
833 			new_conn_state->hdmi.output_bpc,
834 			old_conn_state->hdmi.output_bpc);
835 
836 	ret = drm_atomic_check_only(state);
837 	KUNIT_ASSERT_EQ(test, ret, 0);
838 
839 	old_conn_state = drm_atomic_get_old_connector_state(state, conn);
840 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
841 
842 	new_conn_state = drm_atomic_get_new_connector_state(state, conn);
843 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
844 
845 	KUNIT_EXPECT_EQ(test,
846 			old_conn_state->hdmi.output_bpc,
847 			new_conn_state->hdmi.output_bpc);
848 
849 	crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
850 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
851 	KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed);
852 }
853 
854 /*
855  * Test that if we have an HDMI connector but a !HDMI display, we always
856  * output RGB with 8 bpc.
857  */
drm_test_check_output_bpc_dvi(struct kunit * test)858 static void drm_test_check_output_bpc_dvi(struct kunit *test)
859 {
860 	struct drm_atomic_helper_connector_hdmi_priv *priv;
861 	struct drm_modeset_acquire_ctx *ctx;
862 	struct drm_connector_state *conn_state;
863 	struct drm_display_info *info;
864 	struct drm_display_mode *preferred;
865 	struct drm_connector *conn;
866 	struct drm_device *drm;
867 	struct drm_crtc *crtc;
868 	int ret;
869 
870 	priv = drm_atomic_helper_connector_hdmi_init(test,
871 						     BIT(HDMI_COLORSPACE_RGB) |
872 						     BIT(HDMI_COLORSPACE_YUV422) |
873 						     BIT(HDMI_COLORSPACE_YUV444),
874 						     12);
875 	KUNIT_ASSERT_NOT_NULL(test, priv);
876 
877 	drm = &priv->drm;
878 	crtc = priv->crtc;
879 	conn = &priv->connector;
880 	ret = set_connector_edid(test, conn,
881 				 test_edid_dvi_1080p,
882 				 ARRAY_SIZE(test_edid_dvi_1080p));
883 	KUNIT_ASSERT_GT(test, ret, 0);
884 
885 	info = &conn->display_info;
886 	KUNIT_ASSERT_FALSE(test, info->is_hdmi);
887 
888 	preferred = find_preferred_mode(conn);
889 	KUNIT_ASSERT_NOT_NULL(test, preferred);
890 
891 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
892 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
893 
894 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
895 	KUNIT_ASSERT_EQ(test, ret, 0);
896 
897 	conn_state = conn->state;
898 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
899 
900 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
901 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
902 }
903 
904 /*
905  * Test that when doing a commit which would use RGB 8bpc, the TMDS
906  * clock rate stored in the connector state is equal to the mode clock
907  */
drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit * test)908 static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test)
909 {
910 	struct drm_atomic_helper_connector_hdmi_priv *priv;
911 	struct drm_modeset_acquire_ctx *ctx;
912 	struct drm_connector_state *conn_state;
913 	struct drm_display_mode *preferred;
914 	struct drm_connector *conn;
915 	struct drm_device *drm;
916 	struct drm_crtc *crtc;
917 	int ret;
918 
919 	priv = drm_atomic_helper_connector_hdmi_init(test,
920 						     BIT(HDMI_COLORSPACE_RGB),
921 						     8);
922 	KUNIT_ASSERT_NOT_NULL(test, priv);
923 
924 	drm = &priv->drm;
925 	crtc = priv->crtc;
926 	conn = &priv->connector;
927 	ret = set_connector_edid(test, conn,
928 				 test_edid_hdmi_1080p_rgb_max_200mhz,
929 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz));
930 	KUNIT_ASSERT_GT(test, ret, 0);
931 
932 	preferred = find_preferred_mode(conn);
933 	KUNIT_ASSERT_NOT_NULL(test, preferred);
934 	KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
935 
936 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
937 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
938 
939 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
940 	KUNIT_ASSERT_EQ(test, ret, 0);
941 
942 	conn_state = conn->state;
943 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
944 
945 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 8);
946 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
947 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1000);
948 }
949 
950 /*
951  * Test that when doing a commit which would use RGB 10bpc, the TMDS
952  * clock rate stored in the connector state is equal to 1.25 times the
953  * mode pixel clock
954  */
drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit * test)955 static void drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit *test)
956 {
957 	struct drm_atomic_helper_connector_hdmi_priv *priv;
958 	struct drm_modeset_acquire_ctx *ctx;
959 	struct drm_connector_state *conn_state;
960 	struct drm_display_mode *preferred;
961 	struct drm_connector *conn;
962 	struct drm_device *drm;
963 	struct drm_crtc *crtc;
964 	int ret;
965 
966 	priv = drm_atomic_helper_connector_hdmi_init(test,
967 						     BIT(HDMI_COLORSPACE_RGB),
968 						     10);
969 	KUNIT_ASSERT_NOT_NULL(test, priv);
970 
971 	drm = &priv->drm;
972 	crtc = priv->crtc;
973 	conn = &priv->connector;
974 	ret = set_connector_edid(test, conn,
975 				 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz,
976 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz));
977 	KUNIT_ASSERT_GT(test, ret, 0);
978 
979 	preferred = find_preferred_mode(conn);
980 	KUNIT_ASSERT_NOT_NULL(test, preferred);
981 	KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
982 
983 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
984 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
985 
986 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
987 	KUNIT_ASSERT_EQ(test, ret, 0);
988 
989 	conn_state = conn->state;
990 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
991 
992 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 10);
993 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
994 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250);
995 }
996 
997 /*
998  * Test that when doing a commit which would use RGB 12bpc, the TMDS
999  * clock rate stored in the connector state is equal to 1.5 times the
1000  * mode pixel clock
1001  */
drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit * test)1002 static void drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test)
1003 {
1004 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1005 	struct drm_modeset_acquire_ctx *ctx;
1006 	struct drm_connector_state *conn_state;
1007 	struct drm_display_mode *preferred;
1008 	struct drm_connector *conn;
1009 	struct drm_device *drm;
1010 	struct drm_crtc *crtc;
1011 	int ret;
1012 
1013 	priv = drm_atomic_helper_connector_hdmi_init(test,
1014 						     BIT(HDMI_COLORSPACE_RGB),
1015 						     12);
1016 	KUNIT_ASSERT_NOT_NULL(test, priv);
1017 
1018 	drm = &priv->drm;
1019 	crtc = priv->crtc;
1020 	conn = &priv->connector;
1021 	ret = set_connector_edid(test, conn,
1022 				 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz,
1023 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz));
1024 	KUNIT_ASSERT_GT(test, ret, 0);
1025 
1026 	preferred = find_preferred_mode(conn);
1027 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1028 	KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
1029 
1030 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1031 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1032 
1033 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1034 	KUNIT_ASSERT_EQ(test, ret, 0);
1035 
1036 	conn_state = conn->state;
1037 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1038 
1039 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 12);
1040 	KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1041 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1500);
1042 }
1043 
1044 /*
1045  * Test that if we filter a rate through our hook, it's indeed rejected
1046  * by the whole atomic_check logic.
1047  *
1048  * We do so by first doing a commit on the pipeline to make sure that it
1049  * works, change the HDMI helpers pointer, and then try the same commit
1050  * again to see if it fails as it should.
1051  */
drm_test_check_hdmi_funcs_reject_rate(struct kunit * test)1052 static void drm_test_check_hdmi_funcs_reject_rate(struct kunit *test)
1053 {
1054 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1055 	struct drm_modeset_acquire_ctx *ctx;
1056 	struct drm_atomic_state *state;
1057 	struct drm_display_mode *preferred;
1058 	struct drm_crtc_state *crtc_state;
1059 	struct drm_connector *conn;
1060 	struct drm_device *drm;
1061 	struct drm_crtc *crtc;
1062 	int ret;
1063 
1064 	priv = drm_atomic_helper_connector_hdmi_init(test,
1065 						     BIT(HDMI_COLORSPACE_RGB),
1066 						     8);
1067 	KUNIT_ASSERT_NOT_NULL(test, priv);
1068 
1069 	drm = &priv->drm;
1070 	crtc = priv->crtc;
1071 	conn = &priv->connector;
1072 
1073 	preferred = find_preferred_mode(conn);
1074 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1075 
1076 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1077 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1078 
1079 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1080 	KUNIT_ASSERT_EQ(test, ret, 0);
1081 
1082 	/* You shouldn't be doing that at home. */
1083 	conn->hdmi.funcs = &reject_connector_hdmi_funcs;
1084 
1085 	state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
1086 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1087 
1088 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
1089 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1090 
1091 	crtc_state->connectors_changed = true;
1092 
1093 	ret = drm_atomic_check_only(state);
1094 	KUNIT_EXPECT_LT(test, ret, 0);
1095 }
1096 
1097 /*
1098  * Test that if:
1099  * - We have an HDMI connector supporting RGB only
1100  * - The chosen mode has a TMDS character rate higher than the display
1101  *   supports in RGB/12bpc
1102  * - The chosen mode has a TMDS character rate lower than the display
1103  *   supports in RGB/10bpc.
1104  *
1105  * Then we will pick the latter, and the computed TMDS character rate
1106  * will be equal to 1.25 times the mode pixel clock.
1107  */
drm_test_check_max_tmds_rate_bpc_fallback(struct kunit * test)1108 static void drm_test_check_max_tmds_rate_bpc_fallback(struct kunit *test)
1109 {
1110 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1111 	struct drm_modeset_acquire_ctx *ctx;
1112 	struct drm_connector_state *conn_state;
1113 	struct drm_display_info *info;
1114 	struct drm_display_mode *preferred;
1115 	unsigned long long rate;
1116 	struct drm_connector *conn;
1117 	struct drm_device *drm;
1118 	struct drm_crtc *crtc;
1119 	int ret;
1120 
1121 	priv = drm_atomic_helper_connector_hdmi_init(test,
1122 						     BIT(HDMI_COLORSPACE_RGB),
1123 						     12);
1124 	KUNIT_ASSERT_NOT_NULL(test, priv);
1125 
1126 	drm = &priv->drm;
1127 	crtc = priv->crtc;
1128 	conn = &priv->connector;
1129 	ret = set_connector_edid(test, conn,
1130 				 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
1131 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
1132 	KUNIT_ASSERT_GT(test, ret, 0);
1133 
1134 	info = &conn->display_info;
1135 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1136 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1137 
1138 	preferred = find_preferred_mode(conn);
1139 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1140 	KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
1141 
1142 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1143 	KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1144 
1145 	rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB);
1146 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1147 
1148 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1149 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1150 
1151 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1152 	KUNIT_EXPECT_EQ(test, ret, 0);
1153 
1154 	conn_state = conn->state;
1155 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1156 
1157 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10);
1158 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1159 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250);
1160 }
1161 
1162 /*
1163  * Test that if:
1164  * - We have an HDMI connector supporting both RGB and YUV422 and up to
1165  *   12 bpc
1166  * - The chosen mode has a TMDS character rate higher than the display
1167  *   supports in RGB/12bpc but lower than the display supports in
1168  *   RGB/10bpc
1169  * - The chosen mode has a TMDS character rate lower than the display
1170  *   supports in YUV422/12bpc.
1171  *
1172  * Then we will prefer to keep the RGB format with a lower bpc over
1173  * picking YUV422.
1174  */
drm_test_check_max_tmds_rate_format_fallback(struct kunit * test)1175 static void drm_test_check_max_tmds_rate_format_fallback(struct kunit *test)
1176 {
1177 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1178 	struct drm_modeset_acquire_ctx *ctx;
1179 	struct drm_connector_state *conn_state;
1180 	struct drm_display_info *info;
1181 	struct drm_display_mode *preferred;
1182 	unsigned long long rate;
1183 	struct drm_connector *conn;
1184 	struct drm_device *drm;
1185 	struct drm_crtc *crtc;
1186 	int ret;
1187 
1188 	priv = drm_atomic_helper_connector_hdmi_init(test,
1189 						     BIT(HDMI_COLORSPACE_RGB) |
1190 						     BIT(HDMI_COLORSPACE_YUV422) |
1191 						     BIT(HDMI_COLORSPACE_YUV444),
1192 						     12);
1193 	KUNIT_ASSERT_NOT_NULL(test, priv);
1194 
1195 	drm = &priv->drm;
1196 	crtc = priv->crtc;
1197 	conn = &priv->connector;
1198 	ret = set_connector_edid(test, conn,
1199 				 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
1200 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
1201 	KUNIT_ASSERT_GT(test, ret, 0);
1202 
1203 	info = &conn->display_info;
1204 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1205 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1206 
1207 	preferred = find_preferred_mode(conn);
1208 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1209 	KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
1210 
1211 	rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB);
1212 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1213 
1214 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1215 	KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1216 
1217 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
1218 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1219 
1220 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1221 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1222 
1223 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1224 	KUNIT_EXPECT_EQ(test, ret, 0);
1225 
1226 	conn_state = conn->state;
1227 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1228 
1229 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10);
1230 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1231 }
1232 
1233 /*
1234  * Test that if a driver and screen supports RGB and YUV formats, and we
1235  * try to set the VIC 1 mode, we end up with 8bpc RGB even if we could
1236  * have had a higher bpc.
1237  */
drm_test_check_output_bpc_format_vic_1(struct kunit * test)1238 static void drm_test_check_output_bpc_format_vic_1(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 *mode;
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_atomic_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 	conn = &priv->connector;
1260 	ret = set_connector_edid(test, conn,
1261 				 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
1262 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
1263 	KUNIT_ASSERT_GT(test, ret, 0);
1264 
1265 	info = &conn->display_info;
1266 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1267 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1268 
1269 	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
1270 	KUNIT_ASSERT_NOT_NULL(test, mode);
1271 
1272 	/*
1273 	 * NOTE: We can't use drm_hdmi_compute_mode_clock()
1274 	 * here because we're trying to get the rate of an invalid
1275 	 * configuration.
1276 	 *
1277 	 * Thus, we have to calculate the rate by hand.
1278 	 */
1279 	rate = mode->clock * 1500;
1280 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1281 
1282 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1283 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1284 
1285 	crtc = priv->crtc;
1286 	ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
1287 	KUNIT_EXPECT_EQ(test, ret, 0);
1288 
1289 	conn_state = conn->state;
1290 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1291 
1292 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
1293 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1294 }
1295 
1296 /*
1297  * Test that if a driver supports only RGB but the screen also supports
1298  * YUV formats, we only end up with an RGB format.
1299  */
drm_test_check_output_bpc_format_driver_rgb_only(struct kunit * test)1300 static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test)
1301 {
1302 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1303 	struct drm_modeset_acquire_ctx *ctx;
1304 	struct drm_connector_state *conn_state;
1305 	struct drm_display_info *info;
1306 	struct drm_display_mode *preferred;
1307 	unsigned long long rate;
1308 	struct drm_connector *conn;
1309 	struct drm_device *drm;
1310 	struct drm_crtc *crtc;
1311 	int ret;
1312 
1313 	priv = drm_atomic_helper_connector_hdmi_init(test,
1314 						     BIT(HDMI_COLORSPACE_RGB),
1315 						     12);
1316 	KUNIT_ASSERT_NOT_NULL(test, priv);
1317 
1318 	drm = &priv->drm;
1319 	crtc = priv->crtc;
1320 	conn = &priv->connector;
1321 	ret = set_connector_edid(test, conn,
1322 				 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
1323 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
1324 	KUNIT_ASSERT_GT(test, ret, 0);
1325 
1326 	info = &conn->display_info;
1327 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1328 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1329 
1330 	preferred = find_preferred_mode(conn);
1331 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1332 
1333 	/*
1334 	 * We're making sure that YUV422 would be the preferred option
1335 	 * here: we're always favouring higher bpc, we can't have RGB
1336 	 * because the TMDS character rate exceeds the maximum supported
1337 	 * by the display, and YUV422 works for that display.
1338 	 *
1339 	 * But since the driver only supports RGB, we should fallback to
1340 	 * a lower bpc with RGB.
1341 	 */
1342 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1343 	KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1344 
1345 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
1346 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1347 
1348 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1349 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1350 
1351 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1352 	KUNIT_EXPECT_EQ(test, ret, 0);
1353 
1354 	conn_state = conn->state;
1355 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1356 
1357 	KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12);
1358 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1359 }
1360 
1361 /*
1362  * Test that if a screen supports only RGB but the driver also supports
1363  * YUV formats, we only end up with an RGB format.
1364  */
drm_test_check_output_bpc_format_display_rgb_only(struct kunit * test)1365 static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test)
1366 {
1367 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1368 	struct drm_modeset_acquire_ctx *ctx;
1369 	struct drm_connector_state *conn_state;
1370 	struct drm_display_info *info;
1371 	struct drm_display_mode *preferred;
1372 	unsigned long long rate;
1373 	struct drm_connector *conn;
1374 	struct drm_device *drm;
1375 	struct drm_crtc *crtc;
1376 	int ret;
1377 
1378 	priv = drm_atomic_helper_connector_hdmi_init(test,
1379 						     BIT(HDMI_COLORSPACE_RGB) |
1380 						     BIT(HDMI_COLORSPACE_YUV422) |
1381 						     BIT(HDMI_COLORSPACE_YUV444),
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_max_200mhz,
1390 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_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 display 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 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1416 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1417 
1418 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1419 	KUNIT_EXPECT_EQ(test, ret, 0);
1420 
1421 	conn_state = conn->state;
1422 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1423 
1424 	KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12);
1425 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1426 }
1427 
1428 /*
1429  * Test that if a display supports higher bpc but the driver only
1430  * supports 8 bpc, we only end up with 8 bpc even if we could have had a
1431  * higher bpc.
1432  */
drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit * test)1433 static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test)
1434 {
1435 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1436 	struct drm_modeset_acquire_ctx *ctx;
1437 	struct drm_connector_state *conn_state;
1438 	struct drm_display_info *info;
1439 	struct drm_display_mode *preferred;
1440 	unsigned long long rate;
1441 	struct drm_connector *conn;
1442 	struct drm_device *drm;
1443 	struct drm_crtc *crtc;
1444 	int ret;
1445 
1446 	priv = drm_atomic_helper_connector_hdmi_init(test,
1447 						     BIT(HDMI_COLORSPACE_RGB),
1448 						     8);
1449 	KUNIT_ASSERT_NOT_NULL(test, priv);
1450 
1451 	drm = &priv->drm;
1452 	crtc = priv->crtc;
1453 	conn = &priv->connector;
1454 	ret = set_connector_edid(test, conn,
1455 				 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz,
1456 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz));
1457 	KUNIT_ASSERT_GT(test, ret, 0);
1458 
1459 	info = &conn->display_info;
1460 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1461 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1462 
1463 	preferred = find_preferred_mode(conn);
1464 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1465 
1466 	/*
1467 	 * We're making sure that we have headroom on the TMDS character
1468 	 * clock to actually use 12bpc.
1469 	 */
1470 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1471 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1472 
1473 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1474 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1475 
1476 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1477 	KUNIT_EXPECT_EQ(test, ret, 0);
1478 
1479 	conn_state = conn->state;
1480 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1481 
1482 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
1483 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1484 }
1485 
1486 /*
1487  * Test that if a driver supports higher bpc but the display only
1488  * supports 8 bpc, we only end up with 8 bpc even if we could have had a
1489  * higher bpc.
1490  */
drm_test_check_output_bpc_format_display_8bpc_only(struct kunit * test)1491 static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *test)
1492 {
1493 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1494 	struct drm_modeset_acquire_ctx *ctx;
1495 	struct drm_connector_state *conn_state;
1496 	struct drm_display_info *info;
1497 	struct drm_display_mode *preferred;
1498 	unsigned long long rate;
1499 	struct drm_connector *conn;
1500 	struct drm_device *drm;
1501 	struct drm_crtc *crtc;
1502 	int ret;
1503 
1504 	priv = drm_atomic_helper_connector_hdmi_init(test,
1505 						     BIT(HDMI_COLORSPACE_RGB) |
1506 						     BIT(HDMI_COLORSPACE_YUV422) |
1507 						     BIT(HDMI_COLORSPACE_YUV444),
1508 						     12);
1509 	KUNIT_ASSERT_NOT_NULL(test, priv);
1510 
1511 	drm = &priv->drm;
1512 	crtc = priv->crtc;
1513 	conn = &priv->connector;
1514 	ret = set_connector_edid(test, conn,
1515 				 test_edid_hdmi_1080p_rgb_max_340mhz,
1516 				 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_340mhz));
1517 	KUNIT_ASSERT_GT(test, ret, 0);
1518 
1519 	info = &conn->display_info;
1520 	KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1521 	KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1522 
1523 	preferred = find_preferred_mode(conn);
1524 	KUNIT_ASSERT_NOT_NULL(test, preferred);
1525 
1526 	/*
1527 	 * We're making sure that we have headroom on the TMDS character
1528 	 * clock to actually use 12bpc.
1529 	 */
1530 	rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1531 	KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1532 
1533 	ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1534 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1535 
1536 	ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1537 	KUNIT_EXPECT_EQ(test, ret, 0);
1538 
1539 	conn_state = conn->state;
1540 	KUNIT_ASSERT_NOT_NULL(test, conn_state);
1541 
1542 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
1543 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1544 }
1545 
1546 static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = {
1547 	KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode),
1548 	KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode_vic_1),
1549 	KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode),
1550 	KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode_vic_1),
1551 	KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode),
1552 	KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode_vic_1),
1553 	/*
1554 	 * TODO: When we'll have YUV output support, we need to check
1555 	 * that the limited range is always set to limited no matter
1556 	 * what the value of Broadcast RGB is.
1557 	 */
1558 	KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_changed),
1559 	KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_not_changed),
1560 	KUNIT_CASE(drm_test_check_hdmi_funcs_reject_rate),
1561 	KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback),
1562 	KUNIT_CASE(drm_test_check_max_tmds_rate_format_fallback),
1563 	KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_changed),
1564 	KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_not_changed),
1565 	KUNIT_CASE(drm_test_check_output_bpc_dvi),
1566 	KUNIT_CASE(drm_test_check_output_bpc_format_vic_1),
1567 	KUNIT_CASE(drm_test_check_output_bpc_format_display_8bpc_only),
1568 	KUNIT_CASE(drm_test_check_output_bpc_format_display_rgb_only),
1569 	KUNIT_CASE(drm_test_check_output_bpc_format_driver_8bpc_only),
1570 	KUNIT_CASE(drm_test_check_output_bpc_format_driver_rgb_only),
1571 	KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_8bpc),
1572 	KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_10bpc),
1573 	KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_12bpc),
1574 	/*
1575 	 * TODO: We should have tests to check that a change in the
1576 	 * format triggers a CRTC mode change just like we do for the
1577 	 * RGB Quantization and BPC.
1578 	 *
1579 	 * However, we don't have any way to control which format gets
1580 	 * picked up aside from changing the BPC or mode which would
1581 	 * already trigger a mode change.
1582 	 */
1583 	{ }
1584 };
1585 
1586 static struct kunit_suite drm_atomic_helper_connector_hdmi_check_test_suite = {
1587 	.name		= "drm_atomic_helper_connector_hdmi_check",
1588 	.test_cases	= drm_atomic_helper_connector_hdmi_check_tests,
1589 };
1590 
1591 /*
1592  * Test that the value of the Broadcast RGB property out of reset is set
1593  * to auto.
1594  */
drm_test_check_broadcast_rgb_value(struct kunit * test)1595 static void drm_test_check_broadcast_rgb_value(struct kunit *test)
1596 {
1597 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1598 	struct drm_connector_state *conn_state;
1599 	struct drm_connector *conn;
1600 
1601 	priv = drm_atomic_helper_connector_hdmi_init(test,
1602 						     BIT(HDMI_COLORSPACE_RGB),
1603 						     8);
1604 	KUNIT_ASSERT_NOT_NULL(test, priv);
1605 
1606 	conn = &priv->connector;
1607 	conn_state = conn->state;
1608 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_AUTO);
1609 }
1610 
1611 /*
1612  * Test that if the connector was initialised with a maximum bpc of 8,
1613  * the value of the max_bpc and max_requested_bpc properties out of
1614  * reset are also set to 8, and output_bpc is set to 0 and will be
1615  * filled at atomic_check time.
1616  */
drm_test_check_bpc_8_value(struct kunit * test)1617 static void drm_test_check_bpc_8_value(struct kunit *test)
1618 {
1619 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1620 	struct drm_connector_state *conn_state;
1621 	struct drm_connector *conn;
1622 
1623 	priv = drm_atomic_helper_connector_hdmi_init(test,
1624 						     BIT(HDMI_COLORSPACE_RGB),
1625 						     8);
1626 	KUNIT_ASSERT_NOT_NULL(test, priv);
1627 
1628 	conn = &priv->connector;
1629 	conn_state = conn->state;
1630 	KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 8);
1631 	KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 8);
1632 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0);
1633 }
1634 
1635 /*
1636  * Test that if the connector was initialised with a maximum bpc of 10,
1637  * the value of the max_bpc and max_requested_bpc properties out of
1638  * reset are also set to 10, and output_bpc is set to 0 and will be
1639  * filled at atomic_check time.
1640  */
drm_test_check_bpc_10_value(struct kunit * test)1641 static void drm_test_check_bpc_10_value(struct kunit *test)
1642 {
1643 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1644 	struct drm_connector_state *conn_state;
1645 	struct drm_connector *conn;
1646 
1647 	priv = drm_atomic_helper_connector_hdmi_init(test,
1648 						     BIT(HDMI_COLORSPACE_RGB),
1649 						     10);
1650 	KUNIT_ASSERT_NOT_NULL(test, priv);
1651 
1652 	conn = &priv->connector;
1653 	conn_state = conn->state;
1654 	KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 10);
1655 	KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 10);
1656 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0);
1657 }
1658 
1659 /*
1660  * Test that if the connector was initialised with a maximum bpc of 12,
1661  * the value of the max_bpc and max_requested_bpc properties out of
1662  * reset are also set to 12, and output_bpc is set to 0 and will be
1663  * filled at atomic_check time.
1664  */
drm_test_check_bpc_12_value(struct kunit * test)1665 static void drm_test_check_bpc_12_value(struct kunit *test)
1666 {
1667 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1668 	struct drm_connector_state *conn_state;
1669 	struct drm_connector *conn;
1670 
1671 	priv = drm_atomic_helper_connector_hdmi_init(test,
1672 						     BIT(HDMI_COLORSPACE_RGB),
1673 						     12);
1674 	KUNIT_ASSERT_NOT_NULL(test, priv);
1675 
1676 	conn = &priv->connector;
1677 	conn_state = conn->state;
1678 	KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 12);
1679 	KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 12);
1680 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0);
1681 }
1682 
1683 /*
1684  * Test that the value of the output format property out of reset is set
1685  * to RGB, even if the driver supports more than that.
1686  */
drm_test_check_format_value(struct kunit * test)1687 static void drm_test_check_format_value(struct kunit *test)
1688 {
1689 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1690 	struct drm_connector_state *conn_state;
1691 	struct drm_connector *conn;
1692 
1693 	priv = drm_atomic_helper_connector_hdmi_init(test,
1694 						     BIT(HDMI_COLORSPACE_RGB) |
1695 						     BIT(HDMI_COLORSPACE_YUV422) |
1696 						     BIT(HDMI_COLORSPACE_YUV444),
1697 						     8);
1698 	KUNIT_ASSERT_NOT_NULL(test, priv);
1699 
1700 	conn = &priv->connector;
1701 	conn_state = conn->state;
1702 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, 0);
1703 }
1704 
1705 /*
1706  * Test that the value of the output format property out of reset is set
1707  * to 0, and will be computed at atomic_check time.
1708  */
drm_test_check_tmds_char_value(struct kunit * test)1709 static void drm_test_check_tmds_char_value(struct kunit *test)
1710 {
1711 	struct drm_atomic_helper_connector_hdmi_priv *priv;
1712 	struct drm_connector_state *conn_state;
1713 	struct drm_connector *conn;
1714 
1715 	priv = drm_atomic_helper_connector_hdmi_init(test,
1716 						     BIT(HDMI_COLORSPACE_RGB) |
1717 						     BIT(HDMI_COLORSPACE_YUV422) |
1718 						     BIT(HDMI_COLORSPACE_YUV444),
1719 						     12);
1720 	KUNIT_ASSERT_NOT_NULL(test, priv);
1721 
1722 	conn = &priv->connector;
1723 	conn_state = conn->state;
1724 	KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, 0);
1725 }
1726 
1727 static struct kunit_case drm_atomic_helper_connector_hdmi_reset_tests[] = {
1728 	KUNIT_CASE(drm_test_check_broadcast_rgb_value),
1729 	KUNIT_CASE(drm_test_check_bpc_8_value),
1730 	KUNIT_CASE(drm_test_check_bpc_10_value),
1731 	KUNIT_CASE(drm_test_check_bpc_12_value),
1732 	KUNIT_CASE(drm_test_check_format_value),
1733 	KUNIT_CASE(drm_test_check_tmds_char_value),
1734 	{ }
1735 };
1736 
1737 static struct kunit_suite drm_atomic_helper_connector_hdmi_reset_test_suite = {
1738 	.name		= "drm_atomic_helper_connector_hdmi_reset",
1739 	.test_cases	= drm_atomic_helper_connector_hdmi_reset_tests,
1740 };
1741 
1742 kunit_test_suites(
1743 	&drm_atomic_helper_connector_hdmi_check_test_suite,
1744 	&drm_atomic_helper_connector_hdmi_reset_test_suite,
1745 );
1746 
1747 MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>");
1748 MODULE_DESCRIPTION("Kunit test for drm_hdmi_state_helper functions");
1749 MODULE_LICENSE("GPL");
1750