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