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