1 // SPDX-License-Identifier: GPL-2.0
4 * Kunit test for drm_hdmi_state_helper functions
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>
20 #include <drm/display/drm_hdmi_helper.h>
21 #include <drm/display/drm_hdmi_state_helper.h>
23 #include "../drm_crtc_internal.h"
25 #include <kunit/test.h>
27 #include "drm_kunit_edid.h"
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;
36 const char *current_edid;
37 size_t current_edid_len;
40 #define connector_to_priv(c) \
41 container_of_const(c, struct drm_atomic_helper_connector_hdmi_priv, connector)
43 static struct drm_display_mode *find_preferred_mode(struct drm_connector *connector)
45 struct drm_device *drm = connector->dev;
46 struct drm_display_mode *mode, *preferred;
48 mutex_lock(&drm->mode_config.mutex);
49 preferred = list_first_entry(&connector->modes, struct drm_display_mode, head);
50 list_for_each_entry(mode, &connector->modes, head)
51 if (mode->type & DRM_MODE_TYPE_PREFERRED)
53 mutex_unlock(&drm->mode_config.mutex);
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)
65 struct drm_atomic_state *state;
66 struct drm_connector_state *conn_state;
67 struct drm_crtc_state *crtc_state;
70 state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
71 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
73 conn_state = drm_atomic_get_connector_state(state, connector);
74 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
76 ret = drm_atomic_set_crtc_for_connector(conn_state, crtc);
77 KUNIT_EXPECT_EQ(test, ret, 0);
79 crtc_state = drm_atomic_get_crtc_state(state, crtc);
80 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
82 ret = drm_atomic_set_mode_for_crtc(crtc_state, mode);
83 KUNIT_EXPECT_EQ(test, ret, 0);
85 crtc_state->enable = true;
86 crtc_state->active = true;
88 ret = drm_atomic_commit(state);
89 KUNIT_ASSERT_EQ(test, ret, 0);
94 static int set_connector_edid(struct kunit *test, struct drm_connector *connector,
95 const char *edid, size_t edid_len)
97 struct drm_atomic_helper_connector_hdmi_priv *priv =
98 connector_to_priv(connector);
99 struct drm_device *drm = connector->dev;
102 priv->current_edid = edid;
103 priv->current_edid_len = edid_len;
105 mutex_lock(&drm->mode_config.mutex);
106 ret = connector->funcs->fill_modes(connector, 4096, 4096);
107 mutex_unlock(&drm->mode_config.mutex);
108 KUNIT_ASSERT_GT(test, ret, 0);
113 static const struct drm_connector_hdmi_funcs dummy_connector_hdmi_funcs = {
116 static enum drm_mode_status
117 reject_connector_tmds_char_rate_valid(const struct drm_connector *connector,
118 const struct drm_display_mode *mode,
119 unsigned long long tmds_rate)
124 static const struct drm_connector_hdmi_funcs reject_connector_hdmi_funcs = {
125 .tmds_char_rate_valid = reject_connector_tmds_char_rate_valid,
128 static int dummy_connector_get_modes(struct drm_connector *connector)
130 struct drm_atomic_helper_connector_hdmi_priv *priv =
131 connector_to_priv(connector);
132 const struct drm_edid *edid;
133 unsigned int num_modes;
135 edid = drm_edid_alloc(priv->current_edid, priv->current_edid_len);
139 drm_edid_connector_update(connector, edid);
140 num_modes = drm_edid_connector_add_modes(connector);
147 static const struct drm_connector_helper_funcs dummy_connector_helper_funcs = {
148 .atomic_check = drm_atomic_helper_connector_hdmi_check,
149 .get_modes = dummy_connector_get_modes,
152 static void dummy_hdmi_connector_reset(struct drm_connector *connector)
154 drm_atomic_helper_connector_reset(connector);
155 __drm_atomic_helper_connector_hdmi_reset(connector, connector->state);
158 static const struct drm_connector_funcs dummy_connector_funcs = {
159 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
160 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
161 .fill_modes = drm_helper_probe_single_connector_modes,
162 .reset = dummy_hdmi_connector_reset,
166 struct drm_atomic_helper_connector_hdmi_priv *
167 drm_atomic_helper_connector_hdmi_init(struct kunit *test,
168 unsigned int formats,
169 unsigned int max_bpc)
171 struct drm_atomic_helper_connector_hdmi_priv *priv;
172 struct drm_connector *conn;
173 struct drm_encoder *enc;
174 struct drm_device *drm;
178 dev = drm_kunit_helper_alloc_device(test);
179 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
181 priv = drm_kunit_helper_alloc_drm_device(test, dev,
182 struct drm_atomic_helper_connector_hdmi_priv, drm,
183 DRIVER_MODESET | DRIVER_ATOMIC);
184 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
188 priv->plane = drm_kunit_helper_create_primary_plane(test, drm,
193 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->plane);
195 priv->crtc = drm_kunit_helper_create_crtc(test, drm,
199 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->crtc);
201 enc = &priv->encoder;
202 ret = drmm_encoder_init(drm, enc, NULL, DRM_MODE_ENCODER_TMDS, NULL);
203 KUNIT_ASSERT_EQ(test, ret, 0);
205 enc->possible_crtcs = drm_crtc_mask(priv->crtc);
207 conn = &priv->connector;
208 ret = drmm_connector_hdmi_init(drm, conn,
210 &dummy_connector_funcs,
211 &dummy_connector_hdmi_funcs,
212 DRM_MODE_CONNECTOR_HDMIA,
216 KUNIT_ASSERT_EQ(test, ret, 0);
218 drm_connector_helper_add(conn, &dummy_connector_helper_funcs);
219 drm_connector_attach_encoder(conn, enc);
221 drm_mode_config_reset(drm);
223 ret = set_connector_edid(test, conn,
224 test_edid_hdmi_1080p_rgb_max_200mhz,
225 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz));
226 KUNIT_ASSERT_EQ(test, ret, 0);
232 * Test that if we change the RGB quantization property to a different
233 * value, we trigger a mode change on the connector's CRTC, which will
234 * in turn disable/enable the connector.
236 static void drm_test_check_broadcast_rgb_crtc_mode_changed(struct kunit *test)
238 struct drm_atomic_helper_connector_hdmi_priv *priv;
239 struct drm_modeset_acquire_ctx *ctx;
240 struct drm_connector_state *old_conn_state;
241 struct drm_connector_state *new_conn_state;
242 struct drm_crtc_state *crtc_state;
243 struct drm_atomic_state *state;
244 struct drm_display_mode *preferred;
245 struct drm_connector *conn;
246 struct drm_device *drm;
247 struct drm_crtc *crtc;
250 priv = drm_atomic_helper_connector_hdmi_init(test,
251 BIT(HDMI_COLORSPACE_RGB),
253 KUNIT_ASSERT_NOT_NULL(test, priv);
255 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
256 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
258 conn = &priv->connector;
259 preferred = find_preferred_mode(conn);
260 KUNIT_ASSERT_NOT_NULL(test, preferred);
264 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
265 KUNIT_ASSERT_EQ(test, ret, 0);
267 state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
268 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
270 new_conn_state = drm_atomic_get_connector_state(state, conn);
271 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
273 old_conn_state = drm_atomic_get_old_connector_state(state, conn);
274 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
276 new_conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
278 KUNIT_ASSERT_NE(test,
279 old_conn_state->hdmi.broadcast_rgb,
280 new_conn_state->hdmi.broadcast_rgb);
282 ret = drm_atomic_check_only(state);
283 KUNIT_ASSERT_EQ(test, ret, 0);
285 new_conn_state = drm_atomic_get_new_connector_state(state, conn);
286 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
287 KUNIT_EXPECT_EQ(test, new_conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_FULL);
289 crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
290 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
291 KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed);
295 * Test that if we set the RGB quantization property to the same value,
296 * we don't trigger a mode change on the connector's CRTC and leave the
297 * connector unaffected.
299 static void drm_test_check_broadcast_rgb_crtc_mode_not_changed(struct kunit *test)
301 struct drm_atomic_helper_connector_hdmi_priv *priv;
302 struct drm_modeset_acquire_ctx *ctx;
303 struct drm_connector_state *old_conn_state;
304 struct drm_connector_state *new_conn_state;
305 struct drm_crtc_state *crtc_state;
306 struct drm_atomic_state *state;
307 struct drm_display_mode *preferred;
308 struct drm_connector *conn;
309 struct drm_device *drm;
310 struct drm_crtc *crtc;
313 priv = drm_atomic_helper_connector_hdmi_init(test,
314 BIT(HDMI_COLORSPACE_RGB),
316 KUNIT_ASSERT_NOT_NULL(test, priv);
318 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
319 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
321 conn = &priv->connector;
322 preferred = find_preferred_mode(conn);
323 KUNIT_ASSERT_NOT_NULL(test, preferred);
327 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
328 KUNIT_ASSERT_EQ(test, ret, 0);
330 state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
331 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
333 new_conn_state = drm_atomic_get_connector_state(state, conn);
334 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
336 old_conn_state = drm_atomic_get_old_connector_state(state, conn);
337 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
339 new_conn_state->hdmi.broadcast_rgb = old_conn_state->hdmi.broadcast_rgb;
341 ret = drm_atomic_check_only(state);
342 KUNIT_ASSERT_EQ(test, ret, 0);
344 old_conn_state = drm_atomic_get_old_connector_state(state, conn);
345 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
347 new_conn_state = drm_atomic_get_new_connector_state(state, conn);
348 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
350 KUNIT_EXPECT_EQ(test,
351 old_conn_state->hdmi.broadcast_rgb,
352 new_conn_state->hdmi.broadcast_rgb);
354 crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
355 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
356 KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed);
360 * Test that for an HDMI connector, with an HDMI monitor, if the
361 * Broadcast RGB property is set to auto with a mode that isn't the
362 * VIC-1 mode, we will get a limited RGB Quantization Range.
364 static void drm_test_check_broadcast_rgb_auto_cea_mode(struct kunit *test)
366 struct drm_atomic_helper_connector_hdmi_priv *priv;
367 struct drm_modeset_acquire_ctx *ctx;
368 struct drm_connector_state *conn_state;
369 struct drm_atomic_state *state;
370 struct drm_display_mode *preferred;
371 struct drm_connector *conn;
372 struct drm_device *drm;
373 struct drm_crtc *crtc;
376 priv = drm_atomic_helper_connector_hdmi_init(test,
377 BIT(HDMI_COLORSPACE_RGB),
379 KUNIT_ASSERT_NOT_NULL(test, priv);
381 conn = &priv->connector;
382 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
384 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
385 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
387 preferred = find_preferred_mode(conn);
388 KUNIT_ASSERT_NOT_NULL(test, preferred);
389 KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
393 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
394 KUNIT_ASSERT_EQ(test, ret, 0);
396 state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
397 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
399 conn_state = drm_atomic_get_connector_state(state, conn);
400 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
402 KUNIT_ASSERT_EQ(test,
403 conn_state->hdmi.broadcast_rgb,
404 DRM_HDMI_BROADCAST_RGB_AUTO);
406 ret = drm_atomic_check_only(state);
407 KUNIT_ASSERT_EQ(test, ret, 0);
409 conn_state = drm_atomic_get_connector_state(state, conn);
410 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
412 KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
416 * Test that for an HDMI connector, with an HDMI monitor, if the
417 * Broadcast RGB property is set to auto with a VIC-1 mode, we will get
418 * a full RGB Quantization Range.
420 static void drm_test_check_broadcast_rgb_auto_cea_mode_vic_1(struct kunit *test)
422 struct drm_atomic_helper_connector_hdmi_priv *priv;
423 struct drm_modeset_acquire_ctx *ctx;
424 struct drm_connector_state *conn_state;
425 struct drm_atomic_state *state;
426 struct drm_display_mode *mode;
427 struct drm_connector *conn;
428 struct drm_device *drm;
429 struct drm_crtc *crtc;
432 priv = drm_atomic_helper_connector_hdmi_init(test,
433 BIT(HDMI_COLORSPACE_RGB),
435 KUNIT_ASSERT_NOT_NULL(test, priv);
438 conn = &priv->connector;
439 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
441 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
442 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
444 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
445 KUNIT_ASSERT_NOT_NULL(test, mode);
449 ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
450 KUNIT_ASSERT_EQ(test, ret, 0);
452 state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
453 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
455 conn_state = drm_atomic_get_connector_state(state, conn);
456 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
458 KUNIT_ASSERT_EQ(test,
459 conn_state->hdmi.broadcast_rgb,
460 DRM_HDMI_BROADCAST_RGB_AUTO);
462 ret = drm_atomic_check_only(state);
463 KUNIT_ASSERT_EQ(test, ret, 0);
465 conn_state = drm_atomic_get_connector_state(state, conn);
466 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
468 KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range);
472 * Test that for an HDMI connector, with an HDMI monitor, if the
473 * Broadcast RGB property is set to full with a mode that isn't the
474 * VIC-1 mode, we will get a full RGB Quantization Range.
476 static void drm_test_check_broadcast_rgb_full_cea_mode(struct kunit *test)
478 struct drm_atomic_helper_connector_hdmi_priv *priv;
479 struct drm_modeset_acquire_ctx *ctx;
480 struct drm_connector_state *conn_state;
481 struct drm_atomic_state *state;
482 struct drm_display_mode *preferred;
483 struct drm_connector *conn;
484 struct drm_device *drm;
485 struct drm_crtc *crtc;
488 priv = drm_atomic_helper_connector_hdmi_init(test,
489 BIT(HDMI_COLORSPACE_RGB),
491 KUNIT_ASSERT_NOT_NULL(test, priv);
493 conn = &priv->connector;
494 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
496 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
497 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
499 preferred = find_preferred_mode(conn);
500 KUNIT_ASSERT_NOT_NULL(test, preferred);
501 KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
505 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
506 KUNIT_ASSERT_EQ(test, ret, 0);
508 state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
509 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
511 conn_state = drm_atomic_get_connector_state(state, conn);
512 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
514 conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
516 ret = drm_atomic_check_only(state);
517 KUNIT_ASSERT_EQ(test, ret, 0);
519 conn_state = drm_atomic_get_connector_state(state, conn);
520 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
522 KUNIT_ASSERT_EQ(test,
523 conn_state->hdmi.broadcast_rgb,
524 DRM_HDMI_BROADCAST_RGB_FULL);
526 KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range);
530 * Test that for an HDMI connector, with an HDMI monitor, if the
531 * Broadcast RGB property is set to full with a VIC-1 mode, we will get
532 * a full RGB Quantization Range.
534 static void drm_test_check_broadcast_rgb_full_cea_mode_vic_1(struct kunit *test)
536 struct drm_atomic_helper_connector_hdmi_priv *priv;
537 struct drm_modeset_acquire_ctx *ctx;
538 struct drm_connector_state *conn_state;
539 struct drm_atomic_state *state;
540 struct drm_display_mode *mode;
541 struct drm_connector *conn;
542 struct drm_device *drm;
543 struct drm_crtc *crtc;
546 priv = drm_atomic_helper_connector_hdmi_init(test,
547 BIT(HDMI_COLORSPACE_RGB),
549 KUNIT_ASSERT_NOT_NULL(test, priv);
552 conn = &priv->connector;
553 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
555 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
556 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
558 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
559 KUNIT_ASSERT_NOT_NULL(test, mode);
563 ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
564 KUNIT_ASSERT_EQ(test, ret, 0);
566 state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
567 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
569 conn_state = drm_atomic_get_connector_state(state, conn);
570 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
572 conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_FULL;
574 ret = drm_atomic_check_only(state);
575 KUNIT_ASSERT_EQ(test, ret, 0);
577 conn_state = drm_atomic_get_connector_state(state, conn);
578 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
580 KUNIT_ASSERT_EQ(test,
581 conn_state->hdmi.broadcast_rgb,
582 DRM_HDMI_BROADCAST_RGB_FULL);
584 KUNIT_EXPECT_FALSE(test, conn_state->hdmi.is_limited_range);
588 * Test that for an HDMI connector, with an HDMI monitor, if the
589 * Broadcast RGB property is set to limited with a mode that isn't the
590 * VIC-1 mode, we will get a limited RGB Quantization Range.
592 static void drm_test_check_broadcast_rgb_limited_cea_mode(struct kunit *test)
594 struct drm_atomic_helper_connector_hdmi_priv *priv;
595 struct drm_modeset_acquire_ctx *ctx;
596 struct drm_connector_state *conn_state;
597 struct drm_atomic_state *state;
598 struct drm_display_mode *preferred;
599 struct drm_connector *conn;
600 struct drm_device *drm;
601 struct drm_crtc *crtc;
604 priv = drm_atomic_helper_connector_hdmi_init(test,
605 BIT(HDMI_COLORSPACE_RGB),
607 KUNIT_ASSERT_NOT_NULL(test, priv);
609 conn = &priv->connector;
610 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
612 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
613 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
615 preferred = find_preferred_mode(conn);
616 KUNIT_ASSERT_NOT_NULL(test, preferred);
617 KUNIT_ASSERT_NE(test, drm_match_cea_mode(preferred), 1);
621 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
622 KUNIT_ASSERT_EQ(test, ret, 0);
624 state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
625 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
627 conn_state = drm_atomic_get_connector_state(state, conn);
628 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
630 conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED;
632 ret = drm_atomic_check_only(state);
633 KUNIT_ASSERT_EQ(test, ret, 0);
635 conn_state = drm_atomic_get_connector_state(state, conn);
636 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
638 KUNIT_ASSERT_EQ(test,
639 conn_state->hdmi.broadcast_rgb,
640 DRM_HDMI_BROADCAST_RGB_LIMITED);
642 KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
646 * Test that for an HDMI connector, with an HDMI monitor, if the
647 * Broadcast RGB property is set to limited with a VIC-1 mode, we will
648 * get a limited RGB Quantization Range.
650 static void drm_test_check_broadcast_rgb_limited_cea_mode_vic_1(struct kunit *test)
652 struct drm_atomic_helper_connector_hdmi_priv *priv;
653 struct drm_modeset_acquire_ctx *ctx;
654 struct drm_connector_state *conn_state;
655 struct drm_atomic_state *state;
656 struct drm_display_mode *mode;
657 struct drm_connector *conn;
658 struct drm_device *drm;
659 struct drm_crtc *crtc;
662 priv = drm_atomic_helper_connector_hdmi_init(test,
663 BIT(HDMI_COLORSPACE_RGB),
665 KUNIT_ASSERT_NOT_NULL(test, priv);
668 conn = &priv->connector;
669 KUNIT_ASSERT_TRUE(test, conn->display_info.is_hdmi);
671 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
672 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
674 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
675 KUNIT_ASSERT_NOT_NULL(test, mode);
679 ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
680 KUNIT_ASSERT_EQ(test, ret, 0);
682 state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
683 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
685 conn_state = drm_atomic_get_connector_state(state, conn);
686 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
688 conn_state->hdmi.broadcast_rgb = DRM_HDMI_BROADCAST_RGB_LIMITED;
690 ret = drm_atomic_check_only(state);
691 KUNIT_ASSERT_EQ(test, ret, 0);
693 conn_state = drm_atomic_get_connector_state(state, conn);
694 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, conn_state);
696 KUNIT_ASSERT_EQ(test,
697 conn_state->hdmi.broadcast_rgb,
698 DRM_HDMI_BROADCAST_RGB_LIMITED);
700 KUNIT_EXPECT_TRUE(test, conn_state->hdmi.is_limited_range);
704 * Test that if we change the maximum bpc property to a different value,
705 * we trigger a mode change on the connector's CRTC, which will in turn
706 * disable/enable the connector.
708 static void drm_test_check_output_bpc_crtc_mode_changed(struct kunit *test)
710 struct drm_atomic_helper_connector_hdmi_priv *priv;
711 struct drm_modeset_acquire_ctx *ctx;
712 struct drm_connector_state *old_conn_state;
713 struct drm_connector_state *new_conn_state;
714 struct drm_crtc_state *crtc_state;
715 struct drm_atomic_state *state;
716 struct drm_display_mode *preferred;
717 struct drm_connector *conn;
718 struct drm_device *drm;
719 struct drm_crtc *crtc;
722 priv = drm_atomic_helper_connector_hdmi_init(test,
723 BIT(HDMI_COLORSPACE_RGB),
725 KUNIT_ASSERT_NOT_NULL(test, priv);
727 conn = &priv->connector;
728 ret = set_connector_edid(test, conn,
729 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
730 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
731 KUNIT_ASSERT_EQ(test, ret, 0);
733 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
734 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
736 preferred = find_preferred_mode(conn);
737 KUNIT_ASSERT_NOT_NULL(test, preferred);
741 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
742 KUNIT_ASSERT_EQ(test, ret, 0);
744 state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
745 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
747 new_conn_state = drm_atomic_get_connector_state(state, conn);
748 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
750 old_conn_state = drm_atomic_get_old_connector_state(state, conn);
751 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
753 new_conn_state->max_requested_bpc = 8;
755 KUNIT_ASSERT_NE(test,
756 old_conn_state->max_requested_bpc,
757 new_conn_state->max_requested_bpc);
759 ret = drm_atomic_check_only(state);
760 KUNIT_ASSERT_EQ(test, ret, 0);
762 old_conn_state = drm_atomic_get_old_connector_state(state, conn);
763 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
765 new_conn_state = drm_atomic_get_new_connector_state(state, conn);
766 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
768 KUNIT_ASSERT_NE(test,
769 old_conn_state->hdmi.output_bpc,
770 new_conn_state->hdmi.output_bpc);
772 crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
773 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
774 KUNIT_EXPECT_TRUE(test, crtc_state->mode_changed);
778 * Test that if we set the output bpc property to the same value, we
779 * don't trigger a mode change on the connector's CRTC and leave the
780 * connector unaffected.
782 static void drm_test_check_output_bpc_crtc_mode_not_changed(struct kunit *test)
784 struct drm_atomic_helper_connector_hdmi_priv *priv;
785 struct drm_modeset_acquire_ctx *ctx;
786 struct drm_connector_state *old_conn_state;
787 struct drm_connector_state *new_conn_state;
788 struct drm_crtc_state *crtc_state;
789 struct drm_atomic_state *state;
790 struct drm_display_mode *preferred;
791 struct drm_connector *conn;
792 struct drm_device *drm;
793 struct drm_crtc *crtc;
796 priv = drm_atomic_helper_connector_hdmi_init(test,
797 BIT(HDMI_COLORSPACE_RGB),
799 KUNIT_ASSERT_NOT_NULL(test, priv);
801 conn = &priv->connector;
802 ret = set_connector_edid(test, conn,
803 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
804 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
805 KUNIT_ASSERT_EQ(test, ret, 0);
807 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
808 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
810 preferred = find_preferred_mode(conn);
811 KUNIT_ASSERT_NOT_NULL(test, preferred);
815 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
816 KUNIT_ASSERT_EQ(test, ret, 0);
818 state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
819 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
821 new_conn_state = drm_atomic_get_connector_state(state, conn);
822 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
824 old_conn_state = drm_atomic_get_old_connector_state(state, conn);
825 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
827 KUNIT_ASSERT_EQ(test,
828 new_conn_state->hdmi.output_bpc,
829 old_conn_state->hdmi.output_bpc);
831 ret = drm_atomic_check_only(state);
832 KUNIT_ASSERT_EQ(test, ret, 0);
834 old_conn_state = drm_atomic_get_old_connector_state(state, conn);
835 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, old_conn_state);
837 new_conn_state = drm_atomic_get_new_connector_state(state, conn);
838 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, new_conn_state);
840 KUNIT_EXPECT_EQ(test,
841 old_conn_state->hdmi.output_bpc,
842 new_conn_state->hdmi.output_bpc);
844 crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
845 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
846 KUNIT_EXPECT_FALSE(test, crtc_state->mode_changed);
850 * Test that if we have an HDMI connector but a !HDMI display, we always
851 * output RGB with 8 bpc.
853 static void drm_test_check_output_bpc_dvi(struct kunit *test)
855 struct drm_atomic_helper_connector_hdmi_priv *priv;
856 struct drm_modeset_acquire_ctx *ctx;
857 struct drm_connector_state *conn_state;
858 struct drm_display_info *info;
859 struct drm_display_mode *preferred;
860 struct drm_connector *conn;
861 struct drm_device *drm;
862 struct drm_crtc *crtc;
865 priv = drm_atomic_helper_connector_hdmi_init(test,
866 BIT(HDMI_COLORSPACE_RGB) |
867 BIT(HDMI_COLORSPACE_YUV422) |
868 BIT(HDMI_COLORSPACE_YUV444),
870 KUNIT_ASSERT_NOT_NULL(test, priv);
872 conn = &priv->connector;
873 ret = set_connector_edid(test, conn,
875 ARRAY_SIZE(test_edid_dvi_1080p));
876 KUNIT_ASSERT_EQ(test, ret, 0);
878 info = &conn->display_info;
879 KUNIT_ASSERT_FALSE(test, info->is_hdmi);
881 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
882 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
884 preferred = find_preferred_mode(conn);
885 KUNIT_ASSERT_NOT_NULL(test, preferred);
889 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
890 KUNIT_ASSERT_EQ(test, ret, 0);
892 conn_state = conn->state;
893 KUNIT_ASSERT_NOT_NULL(test, conn_state);
895 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
896 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
900 * Test that when doing a commit which would use RGB 8bpc, the TMDS
901 * clock rate stored in the connector state is equal to the mode clock
903 static void drm_test_check_tmds_char_rate_rgb_8bpc(struct kunit *test)
905 struct drm_atomic_helper_connector_hdmi_priv *priv;
906 struct drm_modeset_acquire_ctx *ctx;
907 struct drm_connector_state *conn_state;
908 struct drm_display_mode *preferred;
909 struct drm_connector *conn;
910 struct drm_device *drm;
911 struct drm_crtc *crtc;
914 priv = drm_atomic_helper_connector_hdmi_init(test,
915 BIT(HDMI_COLORSPACE_RGB),
917 KUNIT_ASSERT_NOT_NULL(test, priv);
919 conn = &priv->connector;
920 ret = set_connector_edid(test, conn,
921 test_edid_hdmi_1080p_rgb_max_200mhz,
922 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz));
923 KUNIT_ASSERT_EQ(test, ret, 0);
925 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
926 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
928 preferred = find_preferred_mode(conn);
929 KUNIT_ASSERT_NOT_NULL(test, preferred);
930 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
934 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
935 KUNIT_ASSERT_EQ(test, ret, 0);
937 conn_state = conn->state;
938 KUNIT_ASSERT_NOT_NULL(test, conn_state);
940 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 8);
941 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
942 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1000);
946 * Test that when doing a commit which would use RGB 10bpc, the TMDS
947 * clock rate stored in the connector state is equal to 1.25 times the
950 static void drm_test_check_tmds_char_rate_rgb_10bpc(struct kunit *test)
952 struct drm_atomic_helper_connector_hdmi_priv *priv;
953 struct drm_modeset_acquire_ctx *ctx;
954 struct drm_connector_state *conn_state;
955 struct drm_display_mode *preferred;
956 struct drm_connector *conn;
957 struct drm_device *drm;
958 struct drm_crtc *crtc;
961 priv = drm_atomic_helper_connector_hdmi_init(test,
962 BIT(HDMI_COLORSPACE_RGB),
964 KUNIT_ASSERT_NOT_NULL(test, priv);
966 conn = &priv->connector;
967 ret = set_connector_edid(test, conn,
968 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz,
969 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz));
970 KUNIT_ASSERT_EQ(test, ret, 0);
972 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
973 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
975 preferred = find_preferred_mode(conn);
976 KUNIT_ASSERT_NOT_NULL(test, preferred);
977 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
981 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
982 KUNIT_ASSERT_EQ(test, ret, 0);
984 conn_state = conn->state;
985 KUNIT_ASSERT_NOT_NULL(test, conn_state);
987 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 10);
988 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
989 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250);
993 * Test that when doing a commit which would use RGB 12bpc, the TMDS
994 * clock rate stored in the connector state is equal to 1.5 times the
997 static void drm_test_check_tmds_char_rate_rgb_12bpc(struct kunit *test)
999 struct drm_atomic_helper_connector_hdmi_priv *priv;
1000 struct drm_modeset_acquire_ctx *ctx;
1001 struct drm_connector_state *conn_state;
1002 struct drm_display_mode *preferred;
1003 struct drm_connector *conn;
1004 struct drm_device *drm;
1005 struct drm_crtc *crtc;
1008 priv = drm_atomic_helper_connector_hdmi_init(test,
1009 BIT(HDMI_COLORSPACE_RGB),
1011 KUNIT_ASSERT_NOT_NULL(test, priv);
1013 conn = &priv->connector;
1014 ret = set_connector_edid(test, conn,
1015 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz,
1016 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz));
1017 KUNIT_ASSERT_EQ(test, ret, 0);
1019 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1020 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1022 preferred = find_preferred_mode(conn);
1023 KUNIT_ASSERT_NOT_NULL(test, preferred);
1024 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
1028 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1029 KUNIT_ASSERT_EQ(test, ret, 0);
1031 conn_state = conn->state;
1032 KUNIT_ASSERT_NOT_NULL(test, conn_state);
1034 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_bpc, 12);
1035 KUNIT_ASSERT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1036 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1500);
1040 * Test that if we filter a rate through our hook, it's indeed rejected
1041 * by the whole atomic_check logic.
1043 * We do so by first doing a commit on the pipeline to make sure that it
1044 * works, change the HDMI helpers pointer, and then try the same commit
1045 * again to see if it fails as it should.
1047 static void drm_test_check_hdmi_funcs_reject_rate(struct kunit *test)
1049 struct drm_atomic_helper_connector_hdmi_priv *priv;
1050 struct drm_modeset_acquire_ctx *ctx;
1051 struct drm_atomic_state *state;
1052 struct drm_display_mode *preferred;
1053 struct drm_crtc_state *crtc_state;
1054 struct drm_connector *conn;
1055 struct drm_device *drm;
1056 struct drm_crtc *crtc;
1059 priv = drm_atomic_helper_connector_hdmi_init(test,
1060 BIT(HDMI_COLORSPACE_RGB),
1062 KUNIT_ASSERT_NOT_NULL(test, priv);
1064 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1065 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1067 conn = &priv->connector;
1068 preferred = find_preferred_mode(conn);
1069 KUNIT_ASSERT_NOT_NULL(test, preferred);
1073 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1074 KUNIT_ASSERT_EQ(test, ret, 0);
1076 /* You shouldn't be doing that at home. */
1077 conn->hdmi.funcs = &reject_connector_hdmi_funcs;
1079 state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
1080 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
1082 crtc_state = drm_atomic_get_crtc_state(state, crtc);
1083 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
1085 crtc_state->connectors_changed = true;
1087 ret = drm_atomic_check_only(state);
1088 KUNIT_EXPECT_LT(test, ret, 0);
1093 * - We have an HDMI connector supporting RGB only
1094 * - The chosen mode has a TMDS character rate higher than the display
1095 * supports in RGB/12bpc
1096 * - The chosen mode has a TMDS character rate lower than the display
1097 * supports in RGB/10bpc.
1099 * Then we will pick the latter, and the computed TMDS character rate
1100 * will be equal to 1.25 times the mode pixel clock.
1102 static void drm_test_check_max_tmds_rate_bpc_fallback(struct kunit *test)
1104 struct drm_atomic_helper_connector_hdmi_priv *priv;
1105 struct drm_modeset_acquire_ctx *ctx;
1106 struct drm_connector_state *conn_state;
1107 struct drm_display_info *info;
1108 struct drm_display_mode *preferred;
1109 unsigned long long rate;
1110 struct drm_connector *conn;
1111 struct drm_device *drm;
1112 struct drm_crtc *crtc;
1115 priv = drm_atomic_helper_connector_hdmi_init(test,
1116 BIT(HDMI_COLORSPACE_RGB),
1118 KUNIT_ASSERT_NOT_NULL(test, priv);
1120 conn = &priv->connector;
1121 ret = set_connector_edid(test, conn,
1122 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
1123 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
1124 KUNIT_ASSERT_EQ(test, ret, 0);
1126 info = &conn->display_info;
1127 KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1128 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1130 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1131 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1133 preferred = find_preferred_mode(conn);
1134 KUNIT_ASSERT_NOT_NULL(test, preferred);
1135 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
1137 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1138 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1140 rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB);
1141 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1145 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1146 KUNIT_EXPECT_EQ(test, ret, 0);
1148 conn_state = conn->state;
1149 KUNIT_ASSERT_NOT_NULL(test, conn_state);
1151 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10);
1152 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1153 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, preferred->clock * 1250);
1158 * - We have an HDMI connector supporting both RGB and YUV422 and up to
1160 * - The chosen mode has a TMDS character rate higher than the display
1161 * supports in RGB/12bpc but lower than the display supports in
1163 * - The chosen mode has a TMDS character rate lower than the display
1164 * supports in YUV422/12bpc.
1166 * Then we will prefer to keep the RGB format with a lower bpc over
1169 static void drm_test_check_max_tmds_rate_format_fallback(struct kunit *test)
1171 struct drm_atomic_helper_connector_hdmi_priv *priv;
1172 struct drm_modeset_acquire_ctx *ctx;
1173 struct drm_connector_state *conn_state;
1174 struct drm_display_info *info;
1175 struct drm_display_mode *preferred;
1176 unsigned long long rate;
1177 struct drm_connector *conn;
1178 struct drm_device *drm;
1179 struct drm_crtc *crtc;
1182 priv = drm_atomic_helper_connector_hdmi_init(test,
1183 BIT(HDMI_COLORSPACE_RGB) |
1184 BIT(HDMI_COLORSPACE_YUV422) |
1185 BIT(HDMI_COLORSPACE_YUV444),
1187 KUNIT_ASSERT_NOT_NULL(test, priv);
1189 conn = &priv->connector;
1190 ret = set_connector_edid(test, conn,
1191 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
1192 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
1193 KUNIT_ASSERT_EQ(test, ret, 0);
1195 info = &conn->display_info;
1196 KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1197 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1199 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1200 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1202 preferred = find_preferred_mode(conn);
1203 KUNIT_ASSERT_NOT_NULL(test, preferred);
1204 KUNIT_ASSERT_FALSE(test, preferred->flags & DRM_MODE_FLAG_DBLCLK);
1206 rate = drm_hdmi_compute_mode_clock(preferred, 10, HDMI_COLORSPACE_RGB);
1207 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1209 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1210 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1212 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
1213 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1217 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1218 KUNIT_EXPECT_EQ(test, ret, 0);
1220 conn_state = conn->state;
1221 KUNIT_ASSERT_NOT_NULL(test, conn_state);
1223 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 10);
1224 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1228 * Test that if a driver and screen supports RGB and YUV formats, and we
1229 * try to set the VIC 1 mode, we end up with 8bpc RGB even if we could
1230 * have had a higher bpc.
1232 static void drm_test_check_output_bpc_format_vic_1(struct kunit *test)
1234 struct drm_atomic_helper_connector_hdmi_priv *priv;
1235 struct drm_modeset_acquire_ctx *ctx;
1236 struct drm_connector_state *conn_state;
1237 struct drm_display_info *info;
1238 struct drm_display_mode *mode;
1239 unsigned long long rate;
1240 struct drm_connector *conn;
1241 struct drm_device *drm;
1242 struct drm_crtc *crtc;
1245 priv = drm_atomic_helper_connector_hdmi_init(test,
1246 BIT(HDMI_COLORSPACE_RGB) |
1247 BIT(HDMI_COLORSPACE_YUV422) |
1248 BIT(HDMI_COLORSPACE_YUV444),
1250 KUNIT_ASSERT_NOT_NULL(test, priv);
1253 conn = &priv->connector;
1254 ret = set_connector_edid(test, conn,
1255 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
1256 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
1257 KUNIT_ASSERT_EQ(test, ret, 0);
1259 info = &conn->display_info;
1260 KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1261 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1263 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1264 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1266 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
1267 KUNIT_ASSERT_NOT_NULL(test, mode);
1270 * NOTE: We can't use drm_hdmi_compute_mode_clock()
1271 * here because we're trying to get the rate of an invalid
1274 * Thus, we have to calculate the rate by hand.
1276 rate = mode->clock * 1500;
1277 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1281 ret = light_up_connector(test, drm, crtc, conn, mode, ctx);
1282 KUNIT_EXPECT_EQ(test, ret, 0);
1284 conn_state = conn->state;
1285 KUNIT_ASSERT_NOT_NULL(test, conn_state);
1287 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
1288 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1292 * Test that if a driver supports only RGB but the screen also supports
1293 * YUV formats, we only end up with an RGB format.
1295 static void drm_test_check_output_bpc_format_driver_rgb_only(struct kunit *test)
1297 struct drm_atomic_helper_connector_hdmi_priv *priv;
1298 struct drm_modeset_acquire_ctx *ctx;
1299 struct drm_connector_state *conn_state;
1300 struct drm_display_info *info;
1301 struct drm_display_mode *preferred;
1302 unsigned long long rate;
1303 struct drm_connector *conn;
1304 struct drm_device *drm;
1305 struct drm_crtc *crtc;
1308 priv = drm_atomic_helper_connector_hdmi_init(test,
1309 BIT(HDMI_COLORSPACE_RGB),
1311 KUNIT_ASSERT_NOT_NULL(test, priv);
1313 conn = &priv->connector;
1314 ret = set_connector_edid(test, conn,
1315 test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz,
1316 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_200mhz));
1317 KUNIT_ASSERT_EQ(test, ret, 0);
1319 info = &conn->display_info;
1320 KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1321 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1323 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1324 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1326 preferred = find_preferred_mode(conn);
1327 KUNIT_ASSERT_NOT_NULL(test, preferred);
1330 * We're making sure that YUV422 would be the preferred option
1331 * here: we're always favouring higher bpc, we can't have RGB
1332 * because the TMDS character rate exceeds the maximum supported
1333 * by the display, and YUV422 works for that display.
1335 * But since the driver only supports RGB, we should fallback to
1336 * a lower bpc with RGB.
1338 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1339 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1341 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
1342 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1346 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1347 KUNIT_EXPECT_EQ(test, ret, 0);
1349 conn_state = conn->state;
1350 KUNIT_ASSERT_NOT_NULL(test, conn_state);
1352 KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12);
1353 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1357 * Test that if a screen supports only RGB but the driver also supports
1358 * YUV formats, we only end up with an RGB format.
1360 static void drm_test_check_output_bpc_format_display_rgb_only(struct kunit *test)
1362 struct drm_atomic_helper_connector_hdmi_priv *priv;
1363 struct drm_modeset_acquire_ctx *ctx;
1364 struct drm_connector_state *conn_state;
1365 struct drm_display_info *info;
1366 struct drm_display_mode *preferred;
1367 unsigned long long rate;
1368 struct drm_connector *conn;
1369 struct drm_device *drm;
1370 struct drm_crtc *crtc;
1373 priv = drm_atomic_helper_connector_hdmi_init(test,
1374 BIT(HDMI_COLORSPACE_RGB) |
1375 BIT(HDMI_COLORSPACE_YUV422) |
1376 BIT(HDMI_COLORSPACE_YUV444),
1378 KUNIT_ASSERT_NOT_NULL(test, priv);
1380 conn = &priv->connector;
1381 ret = set_connector_edid(test, conn,
1382 test_edid_hdmi_1080p_rgb_max_200mhz,
1383 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_200mhz));
1384 KUNIT_ASSERT_EQ(test, ret, 0);
1386 info = &conn->display_info;
1387 KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1388 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1390 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1391 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1393 preferred = find_preferred_mode(conn);
1394 KUNIT_ASSERT_NOT_NULL(test, preferred);
1397 * We're making sure that YUV422 would be the preferred option
1398 * here: we're always favouring higher bpc, we can't have RGB
1399 * because the TMDS character rate exceeds the maximum supported
1400 * by the display, and YUV422 works for that display.
1402 * But since the display only supports RGB, we should fallback to
1403 * a lower bpc with RGB.
1405 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1406 KUNIT_ASSERT_GT(test, rate, info->max_tmds_clock * 1000);
1408 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_YUV422);
1409 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1413 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1414 KUNIT_EXPECT_EQ(test, ret, 0);
1416 conn_state = conn->state;
1417 KUNIT_ASSERT_NOT_NULL(test, conn_state);
1419 KUNIT_EXPECT_LT(test, conn_state->hdmi.output_bpc, 12);
1420 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1424 * Test that if a display supports higher bpc but the driver only
1425 * supports 8 bpc, we only end up with 8 bpc even if we could have had a
1428 static void drm_test_check_output_bpc_format_driver_8bpc_only(struct kunit *test)
1430 struct drm_atomic_helper_connector_hdmi_priv *priv;
1431 struct drm_modeset_acquire_ctx *ctx;
1432 struct drm_connector_state *conn_state;
1433 struct drm_display_info *info;
1434 struct drm_display_mode *preferred;
1435 unsigned long long rate;
1436 struct drm_connector *conn;
1437 struct drm_device *drm;
1438 struct drm_crtc *crtc;
1441 priv = drm_atomic_helper_connector_hdmi_init(test,
1442 BIT(HDMI_COLORSPACE_RGB),
1444 KUNIT_ASSERT_NOT_NULL(test, priv);
1446 conn = &priv->connector;
1447 ret = set_connector_edid(test, conn,
1448 test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz,
1449 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_yuv_dc_max_340mhz));
1450 KUNIT_ASSERT_EQ(test, ret, 0);
1452 info = &conn->display_info;
1453 KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1454 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1456 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1457 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1459 preferred = find_preferred_mode(conn);
1460 KUNIT_ASSERT_NOT_NULL(test, preferred);
1463 * We're making sure that we have headroom on the TMDS character
1464 * clock to actually use 12bpc.
1466 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1467 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1471 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1472 KUNIT_EXPECT_EQ(test, ret, 0);
1474 conn_state = conn->state;
1475 KUNIT_ASSERT_NOT_NULL(test, conn_state);
1477 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
1478 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1482 * Test that if a driver supports higher bpc but the display only
1483 * supports 8 bpc, we only end up with 8 bpc even if we could have had a
1486 static void drm_test_check_output_bpc_format_display_8bpc_only(struct kunit *test)
1488 struct drm_atomic_helper_connector_hdmi_priv *priv;
1489 struct drm_modeset_acquire_ctx *ctx;
1490 struct drm_connector_state *conn_state;
1491 struct drm_display_info *info;
1492 struct drm_display_mode *preferred;
1493 unsigned long long rate;
1494 struct drm_connector *conn;
1495 struct drm_device *drm;
1496 struct drm_crtc *crtc;
1499 priv = drm_atomic_helper_connector_hdmi_init(test,
1500 BIT(HDMI_COLORSPACE_RGB) |
1501 BIT(HDMI_COLORSPACE_YUV422) |
1502 BIT(HDMI_COLORSPACE_YUV444),
1504 KUNIT_ASSERT_NOT_NULL(test, priv);
1506 conn = &priv->connector;
1507 ret = set_connector_edid(test, conn,
1508 test_edid_hdmi_1080p_rgb_max_340mhz,
1509 ARRAY_SIZE(test_edid_hdmi_1080p_rgb_max_340mhz));
1510 KUNIT_ASSERT_EQ(test, ret, 0);
1512 info = &conn->display_info;
1513 KUNIT_ASSERT_TRUE(test, info->is_hdmi);
1514 KUNIT_ASSERT_GT(test, info->max_tmds_clock, 0);
1516 ctx = drm_kunit_helper_acquire_ctx_alloc(test);
1517 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
1519 preferred = find_preferred_mode(conn);
1520 KUNIT_ASSERT_NOT_NULL(test, preferred);
1523 * We're making sure that we have headroom on the TMDS character
1524 * clock to actually use 12bpc.
1526 rate = drm_hdmi_compute_mode_clock(preferred, 12, HDMI_COLORSPACE_RGB);
1527 KUNIT_ASSERT_LT(test, rate, info->max_tmds_clock * 1000);
1531 ret = light_up_connector(test, drm, crtc, conn, preferred, ctx);
1532 KUNIT_EXPECT_EQ(test, ret, 0);
1534 conn_state = conn->state;
1535 KUNIT_ASSERT_NOT_NULL(test, conn_state);
1537 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 8);
1538 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, HDMI_COLORSPACE_RGB);
1541 static struct kunit_case drm_atomic_helper_connector_hdmi_check_tests[] = {
1542 KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode),
1543 KUNIT_CASE(drm_test_check_broadcast_rgb_auto_cea_mode_vic_1),
1544 KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode),
1545 KUNIT_CASE(drm_test_check_broadcast_rgb_full_cea_mode_vic_1),
1546 KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode),
1547 KUNIT_CASE(drm_test_check_broadcast_rgb_limited_cea_mode_vic_1),
1549 * TODO: When we'll have YUV output support, we need to check
1550 * that the limited range is always set to limited no matter
1551 * what the value of Broadcast RGB is.
1553 KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_changed),
1554 KUNIT_CASE(drm_test_check_broadcast_rgb_crtc_mode_not_changed),
1555 KUNIT_CASE(drm_test_check_hdmi_funcs_reject_rate),
1556 KUNIT_CASE(drm_test_check_max_tmds_rate_bpc_fallback),
1557 KUNIT_CASE(drm_test_check_max_tmds_rate_format_fallback),
1558 KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_changed),
1559 KUNIT_CASE(drm_test_check_output_bpc_crtc_mode_not_changed),
1560 KUNIT_CASE(drm_test_check_output_bpc_dvi),
1561 KUNIT_CASE(drm_test_check_output_bpc_format_vic_1),
1562 KUNIT_CASE(drm_test_check_output_bpc_format_display_8bpc_only),
1563 KUNIT_CASE(drm_test_check_output_bpc_format_display_rgb_only),
1564 KUNIT_CASE(drm_test_check_output_bpc_format_driver_8bpc_only),
1565 KUNIT_CASE(drm_test_check_output_bpc_format_driver_rgb_only),
1566 KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_8bpc),
1567 KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_10bpc),
1568 KUNIT_CASE(drm_test_check_tmds_char_rate_rgb_12bpc),
1570 * TODO: We should have tests to check that a change in the
1571 * format triggers a CRTC mode change just like we do for the
1572 * RGB Quantization and BPC.
1574 * However, we don't have any way to control which format gets
1575 * picked up aside from changing the BPC or mode which would
1576 * already trigger a mode change.
1581 static struct kunit_suite drm_atomic_helper_connector_hdmi_check_test_suite = {
1582 .name = "drm_atomic_helper_connector_hdmi_check",
1583 .test_cases = drm_atomic_helper_connector_hdmi_check_tests,
1587 * Test that the value of the Broadcast RGB property out of reset is set
1590 static void drm_test_check_broadcast_rgb_value(struct kunit *test)
1592 struct drm_atomic_helper_connector_hdmi_priv *priv;
1593 struct drm_connector_state *conn_state;
1594 struct drm_connector *conn;
1596 priv = drm_atomic_helper_connector_hdmi_init(test,
1597 BIT(HDMI_COLORSPACE_RGB),
1599 KUNIT_ASSERT_NOT_NULL(test, priv);
1601 conn = &priv->connector;
1602 conn_state = conn->state;
1603 KUNIT_EXPECT_EQ(test, conn_state->hdmi.broadcast_rgb, DRM_HDMI_BROADCAST_RGB_AUTO);
1607 * Test that if the connector was initialised with a maximum bpc of 8,
1608 * the value of the max_bpc and max_requested_bpc properties out of
1609 * reset are also set to 8, and output_bpc is set to 0 and will be
1610 * filled at atomic_check time.
1612 static void drm_test_check_bpc_8_value(struct kunit *test)
1614 struct drm_atomic_helper_connector_hdmi_priv *priv;
1615 struct drm_connector_state *conn_state;
1616 struct drm_connector *conn;
1618 priv = drm_atomic_helper_connector_hdmi_init(test,
1619 BIT(HDMI_COLORSPACE_RGB),
1621 KUNIT_ASSERT_NOT_NULL(test, priv);
1623 conn = &priv->connector;
1624 conn_state = conn->state;
1625 KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 8);
1626 KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 8);
1627 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0);
1631 * Test that if the connector was initialised with a maximum bpc of 10,
1632 * the value of the max_bpc and max_requested_bpc properties out of
1633 * reset are also set to 10, and output_bpc is set to 0 and will be
1634 * filled at atomic_check time.
1636 static void drm_test_check_bpc_10_value(struct kunit *test)
1638 struct drm_atomic_helper_connector_hdmi_priv *priv;
1639 struct drm_connector_state *conn_state;
1640 struct drm_connector *conn;
1642 priv = drm_atomic_helper_connector_hdmi_init(test,
1643 BIT(HDMI_COLORSPACE_RGB),
1645 KUNIT_ASSERT_NOT_NULL(test, priv);
1647 conn = &priv->connector;
1648 conn_state = conn->state;
1649 KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 10);
1650 KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 10);
1651 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0);
1655 * Test that if the connector was initialised with a maximum bpc of 12,
1656 * the value of the max_bpc and max_requested_bpc properties out of
1657 * reset are also set to 12, and output_bpc is set to 0 and will be
1658 * filled at atomic_check time.
1660 static void drm_test_check_bpc_12_value(struct kunit *test)
1662 struct drm_atomic_helper_connector_hdmi_priv *priv;
1663 struct drm_connector_state *conn_state;
1664 struct drm_connector *conn;
1666 priv = drm_atomic_helper_connector_hdmi_init(test,
1667 BIT(HDMI_COLORSPACE_RGB),
1669 KUNIT_ASSERT_NOT_NULL(test, priv);
1671 conn = &priv->connector;
1672 conn_state = conn->state;
1673 KUNIT_EXPECT_EQ(test, conn_state->max_bpc, 12);
1674 KUNIT_EXPECT_EQ(test, conn_state->max_requested_bpc, 12);
1675 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_bpc, 0);
1679 * Test that the value of the output format property out of reset is set
1680 * to RGB, even if the driver supports more than that.
1682 static void drm_test_check_format_value(struct kunit *test)
1684 struct drm_atomic_helper_connector_hdmi_priv *priv;
1685 struct drm_connector_state *conn_state;
1686 struct drm_connector *conn;
1688 priv = drm_atomic_helper_connector_hdmi_init(test,
1689 BIT(HDMI_COLORSPACE_RGB) |
1690 BIT(HDMI_COLORSPACE_YUV422) |
1691 BIT(HDMI_COLORSPACE_YUV444),
1693 KUNIT_ASSERT_NOT_NULL(test, priv);
1695 conn = &priv->connector;
1696 conn_state = conn->state;
1697 KUNIT_EXPECT_EQ(test, conn_state->hdmi.output_format, 0);
1701 * Test that the value of the output format property out of reset is set
1702 * to 0, and will be computed at atomic_check time.
1704 static void drm_test_check_tmds_char_value(struct kunit *test)
1706 struct drm_atomic_helper_connector_hdmi_priv *priv;
1707 struct drm_connector_state *conn_state;
1708 struct drm_connector *conn;
1710 priv = drm_atomic_helper_connector_hdmi_init(test,
1711 BIT(HDMI_COLORSPACE_RGB) |
1712 BIT(HDMI_COLORSPACE_YUV422) |
1713 BIT(HDMI_COLORSPACE_YUV444),
1715 KUNIT_ASSERT_NOT_NULL(test, priv);
1717 conn = &priv->connector;
1718 conn_state = conn->state;
1719 KUNIT_EXPECT_EQ(test, conn_state->hdmi.tmds_char_rate, 0);
1722 static struct kunit_case drm_atomic_helper_connector_hdmi_reset_tests[] = {
1723 KUNIT_CASE(drm_test_check_broadcast_rgb_value),
1724 KUNIT_CASE(drm_test_check_bpc_8_value),
1725 KUNIT_CASE(drm_test_check_bpc_10_value),
1726 KUNIT_CASE(drm_test_check_bpc_12_value),
1727 KUNIT_CASE(drm_test_check_format_value),
1728 KUNIT_CASE(drm_test_check_tmds_char_value),
1732 static struct kunit_suite drm_atomic_helper_connector_hdmi_reset_test_suite = {
1733 .name = "drm_atomic_helper_connector_hdmi_reset",
1734 .test_cases = drm_atomic_helper_connector_hdmi_reset_tests,
1738 &drm_atomic_helper_connector_hdmi_check_test_suite,
1739 &drm_atomic_helper_connector_hdmi_reset_test_suite,
1743 MODULE_DESCRIPTION("Kunit test for drm_hdmi_state_helper functions");
1744 MODULE_LICENSE("GPL");