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