]> Git Repo - J-linux.git/blob - drivers/gpu/drm/tests/drm_hdmi_state_helper_test.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / gpu / drm / tests / drm_hdmi_state_helper_test.c
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
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
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
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
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
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
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 *
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 <[email protected]>");
1743 MODULE_DESCRIPTION("Kunit test for drm_hdmi_state_helper functions");
1744 MODULE_LICENSE("GPL");
This page took 0.128795 seconds and 4 git commands to generate.