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