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