Loading...
Note: File does not exist in v5.4.
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Kunit test for drm_modes functions
4 */
5
6#include <linux/i2c.h>
7
8#include <drm/drm_atomic_state_helper.h>
9#include <drm/drm_connector.h>
10#include <drm/drm_drv.h>
11#include <drm/drm_edid.h>
12#include <drm/drm_kunit_helpers.h>
13#include <drm/drm_modes.h>
14
15#include <drm/display/drm_hdmi_helper.h>
16
17#include <kunit/test.h>
18
19#include "../drm_crtc_internal.h"
20
21struct drm_connector_init_priv {
22 struct drm_device drm;
23 struct drm_connector connector;
24 struct i2c_adapter ddc;
25};
26
27static const struct drm_connector_hdmi_funcs dummy_hdmi_funcs = {
28};
29
30static const struct drm_connector_funcs dummy_funcs = {
31 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
32 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
33 .reset = drm_atomic_helper_connector_reset,
34};
35
36static int dummy_ddc_xfer(struct i2c_adapter *adapter,
37 struct i2c_msg *msgs, int num)
38{
39 return num;
40}
41
42static u32 dummy_ddc_func(struct i2c_adapter *adapter)
43{
44 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
45}
46
47static const struct i2c_algorithm dummy_ddc_algorithm = {
48 .master_xfer = dummy_ddc_xfer,
49 .functionality = dummy_ddc_func,
50};
51
52static void i2c_del_adapter_wrapper(void *ptr)
53{
54 struct i2c_adapter *adap = ptr;
55
56 i2c_del_adapter(adap);
57}
58
59static int drm_test_connector_init(struct kunit *test)
60{
61 struct drm_connector_init_priv *priv;
62 struct device *dev;
63 int ret;
64
65 dev = drm_kunit_helper_alloc_device(test);
66 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
67
68 priv = drm_kunit_helper_alloc_drm_device(test, dev,
69 struct drm_connector_init_priv, drm,
70 DRIVER_MODESET | DRIVER_ATOMIC);
71 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
72
73 strscpy(priv->ddc.name, "dummy-connector-ddc", sizeof(priv->ddc.name));
74 priv->ddc.owner = THIS_MODULE;
75 priv->ddc.algo = &dummy_ddc_algorithm;
76 priv->ddc.dev.parent = dev;
77
78 ret = i2c_add_adapter(&priv->ddc);
79 KUNIT_ASSERT_EQ(test, ret, 0);
80
81 ret = kunit_add_action_or_reset(test, i2c_del_adapter_wrapper, &priv->ddc);
82 KUNIT_ASSERT_EQ(test, ret, 0);
83
84 test->priv = priv;
85 return 0;
86}
87
88/*
89 * Test that the registration of a bog standard connector works as
90 * expected and doesn't report any error.
91 */
92static void drm_test_drmm_connector_init(struct kunit *test)
93{
94 struct drm_connector_init_priv *priv = test->priv;
95 int ret;
96
97 ret = drmm_connector_init(&priv->drm, &priv->connector,
98 &dummy_funcs,
99 DRM_MODE_CONNECTOR_HDMIA,
100 &priv->ddc);
101 KUNIT_EXPECT_EQ(test, ret, 0);
102}
103
104/*
105 * Test that the registration of a connector without a DDC adapter
106 * doesn't report any error.
107 */
108static void drm_test_drmm_connector_init_null_ddc(struct kunit *test)
109{
110 struct drm_connector_init_priv *priv = test->priv;
111 int ret;
112
113 ret = drmm_connector_init(&priv->drm, &priv->connector,
114 &dummy_funcs,
115 DRM_MODE_CONNECTOR_HDMIA,
116 NULL);
117 KUNIT_EXPECT_EQ(test, ret, 0);
118}
119
120/*
121 * Test that the registration of a connector succeeds for all possible
122 * connector types.
123 */
124static void drm_test_drmm_connector_init_type_valid(struct kunit *test)
125{
126 struct drm_connector_init_priv *priv = test->priv;
127 unsigned int connector_type = *(unsigned int *)test->param_value;
128 int ret;
129
130 ret = drmm_connector_init(&priv->drm, &priv->connector,
131 &dummy_funcs,
132 connector_type,
133 &priv->ddc);
134 KUNIT_EXPECT_EQ(test, ret, 0);
135}
136
137static const unsigned int drm_connector_init_type_valid_tests[] = {
138 DRM_MODE_CONNECTOR_Unknown,
139 DRM_MODE_CONNECTOR_VGA,
140 DRM_MODE_CONNECTOR_DVII,
141 DRM_MODE_CONNECTOR_DVID,
142 DRM_MODE_CONNECTOR_DVIA,
143 DRM_MODE_CONNECTOR_Composite,
144 DRM_MODE_CONNECTOR_SVIDEO,
145 DRM_MODE_CONNECTOR_LVDS,
146 DRM_MODE_CONNECTOR_Component,
147 DRM_MODE_CONNECTOR_9PinDIN,
148 DRM_MODE_CONNECTOR_DisplayPort,
149 DRM_MODE_CONNECTOR_HDMIA,
150 DRM_MODE_CONNECTOR_HDMIB,
151 DRM_MODE_CONNECTOR_TV,
152 DRM_MODE_CONNECTOR_eDP,
153 DRM_MODE_CONNECTOR_VIRTUAL,
154 DRM_MODE_CONNECTOR_DSI,
155 DRM_MODE_CONNECTOR_DPI,
156 DRM_MODE_CONNECTOR_WRITEBACK,
157 DRM_MODE_CONNECTOR_SPI,
158 DRM_MODE_CONNECTOR_USB,
159};
160
161static void drm_connector_init_type_desc(const unsigned int *type, char *desc)
162{
163 sprintf(desc, "%s", drm_get_connector_type_name(*type));
164}
165
166KUNIT_ARRAY_PARAM(drm_connector_init_type_valid,
167 drm_connector_init_type_valid_tests,
168 drm_connector_init_type_desc);
169
170static struct kunit_case drmm_connector_init_tests[] = {
171 KUNIT_CASE(drm_test_drmm_connector_init),
172 KUNIT_CASE(drm_test_drmm_connector_init_null_ddc),
173 KUNIT_CASE_PARAM(drm_test_drmm_connector_init_type_valid,
174 drm_connector_init_type_valid_gen_params),
175 { }
176};
177
178static struct kunit_suite drmm_connector_init_test_suite = {
179 .name = "drmm_connector_init",
180 .init = drm_test_connector_init,
181 .test_cases = drmm_connector_init_tests,
182};
183
184/*
185 * Test that the registration of a bog standard connector works as
186 * expected and doesn't report any error.
187 */
188static void drm_test_connector_hdmi_init_valid(struct kunit *test)
189{
190 struct drm_connector_init_priv *priv = test->priv;
191 int ret;
192
193 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
194 "Vendor", "Product",
195 &dummy_funcs,
196 &dummy_hdmi_funcs,
197 DRM_MODE_CONNECTOR_HDMIA,
198 &priv->ddc,
199 BIT(HDMI_COLORSPACE_RGB),
200 8);
201 KUNIT_EXPECT_EQ(test, ret, 0);
202}
203
204/*
205 * Test that the registration of a connector without a DDC adapter
206 * doesn't report any error.
207 */
208static void drm_test_connector_hdmi_init_null_ddc(struct kunit *test)
209{
210 struct drm_connector_init_priv *priv = test->priv;
211 int ret;
212
213 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
214 "Vendor", "Product",
215 &dummy_funcs,
216 &dummy_hdmi_funcs,
217 DRM_MODE_CONNECTOR_HDMIA,
218 NULL,
219 BIT(HDMI_COLORSPACE_RGB),
220 8);
221 KUNIT_EXPECT_EQ(test, ret, 0);
222}
223
224/*
225 * Test that the registration of an HDMI connector with a NULL vendor
226 * fails.
227 */
228static void drm_test_connector_hdmi_init_null_vendor(struct kunit *test)
229{
230 struct drm_connector_init_priv *priv = test->priv;
231 int ret;
232
233 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
234 NULL, "Product",
235 &dummy_funcs,
236 &dummy_hdmi_funcs,
237 DRM_MODE_CONNECTOR_HDMIA,
238 &priv->ddc,
239 BIT(HDMI_COLORSPACE_RGB),
240 8);
241 KUNIT_EXPECT_LT(test, ret, 0);
242}
243
244/*
245 * Test that the registration of an HDMI connector with a NULL product
246 * fails.
247 */
248static void drm_test_connector_hdmi_init_null_product(struct kunit *test)
249{
250 struct drm_connector_init_priv *priv = test->priv;
251 int ret;
252
253 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
254 "Vendor", NULL,
255 &dummy_funcs,
256 &dummy_hdmi_funcs,
257 DRM_MODE_CONNECTOR_HDMIA,
258 &priv->ddc,
259 BIT(HDMI_COLORSPACE_RGB),
260 8);
261 KUNIT_EXPECT_LT(test, ret, 0);
262}
263
264/*
265 * Test that the registration of a connector with a valid, shorter than
266 * the max length, product name succeeds, and is stored padded with 0.
267 */
268static void drm_test_connector_hdmi_init_product_valid(struct kunit *test)
269{
270 struct drm_connector_init_priv *priv = test->priv;
271 const unsigned char expected_product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] = {
272 'P', 'r', 'o', 'd',
273 };
274 const char *product_name = "Prod";
275 int ret;
276
277 KUNIT_ASSERT_LT(test, strlen(product_name), DRM_CONNECTOR_HDMI_PRODUCT_LEN);
278
279 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
280 "Vendor", product_name,
281 &dummy_funcs,
282 &dummy_hdmi_funcs,
283 DRM_MODE_CONNECTOR_HDMIA,
284 &priv->ddc,
285 BIT(HDMI_COLORSPACE_RGB),
286 8);
287 KUNIT_EXPECT_EQ(test, ret, 0);
288 KUNIT_EXPECT_MEMEQ(test,
289 priv->connector.hdmi.product,
290 expected_product,
291 sizeof(priv->connector.hdmi.product));
292}
293
294/*
295 * Test that the registration of a connector with a valid, at max
296 * length, product name succeeds, and is stored padded without any
297 * trailing \0.
298 */
299static void drm_test_connector_hdmi_init_product_length_exact(struct kunit *test)
300{
301 struct drm_connector_init_priv *priv = test->priv;
302 const unsigned char expected_product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] = {
303 'P', 'r', 'o', 'd', 'u', 'c', 't',
304 'P', 'r', 'o', 'd', 'u', 'c', 't',
305 'P', 'r',
306 };
307 const char *product_name = "ProductProductPr";
308 int ret;
309
310 KUNIT_ASSERT_EQ(test, strlen(product_name), DRM_CONNECTOR_HDMI_PRODUCT_LEN);
311
312 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
313 "Vendor", product_name,
314 &dummy_funcs,
315 &dummy_hdmi_funcs,
316 DRM_MODE_CONNECTOR_HDMIA,
317 &priv->ddc,
318 BIT(HDMI_COLORSPACE_RGB),
319 8);
320 KUNIT_EXPECT_EQ(test, ret, 0);
321 KUNIT_EXPECT_MEMEQ(test,
322 priv->connector.hdmi.product,
323 expected_product,
324 sizeof(priv->connector.hdmi.product));
325}
326
327/*
328 * Test that the registration of a connector with a product name larger
329 * than the maximum length fails.
330 */
331static void drm_test_connector_hdmi_init_product_length_too_long(struct kunit *test)
332{
333 struct drm_connector_init_priv *priv = test->priv;
334 const char *product_name = "ProductProductProduct";
335 int ret;
336
337 KUNIT_ASSERT_GT(test, strlen(product_name), DRM_CONNECTOR_HDMI_PRODUCT_LEN);
338
339 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
340 "Vendor", product_name,
341 &dummy_funcs,
342 &dummy_hdmi_funcs,
343 DRM_MODE_CONNECTOR_HDMIA,
344 &priv->ddc,
345 BIT(HDMI_COLORSPACE_RGB),
346 8);
347 KUNIT_EXPECT_LT(test, ret, 0);
348}
349
350/*
351 * Test that the registration of a connector with a vendor name smaller
352 * than the maximum length succeeds, and is stored padded with zeros.
353 */
354static void drm_test_connector_hdmi_init_vendor_valid(struct kunit *test)
355{
356 struct drm_connector_init_priv *priv = test->priv;
357 const char expected_vendor[DRM_CONNECTOR_HDMI_VENDOR_LEN] = {
358 'V', 'e', 'n', 'd',
359 };
360 const char *vendor_name = "Vend";
361 int ret;
362
363 KUNIT_ASSERT_LT(test, strlen(vendor_name), DRM_CONNECTOR_HDMI_VENDOR_LEN);
364
365 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
366 vendor_name, "Product",
367 &dummy_funcs,
368 &dummy_hdmi_funcs,
369 DRM_MODE_CONNECTOR_HDMIA,
370 &priv->ddc,
371 BIT(HDMI_COLORSPACE_RGB),
372 8);
373 KUNIT_EXPECT_EQ(test, ret, 0);
374 KUNIT_EXPECT_MEMEQ(test,
375 priv->connector.hdmi.vendor,
376 expected_vendor,
377 sizeof(priv->connector.hdmi.vendor));
378}
379
380/*
381 * Test that the registration of a connector with a vendor name at the
382 * maximum length succeeds, and is stored padded without the trailing
383 * zero.
384 */
385static void drm_test_connector_hdmi_init_vendor_length_exact(struct kunit *test)
386{
387 struct drm_connector_init_priv *priv = test->priv;
388 const char expected_vendor[DRM_CONNECTOR_HDMI_VENDOR_LEN] = {
389 'V', 'e', 'n', 'd', 'o', 'r',
390 'V', 'e',
391 };
392 const char *vendor_name = "VendorVe";
393 int ret;
394
395 KUNIT_ASSERT_EQ(test, strlen(vendor_name), DRM_CONNECTOR_HDMI_VENDOR_LEN);
396
397 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
398 vendor_name, "Product",
399 &dummy_funcs,
400 &dummy_hdmi_funcs,
401 DRM_MODE_CONNECTOR_HDMIA,
402 &priv->ddc,
403 BIT(HDMI_COLORSPACE_RGB),
404 8);
405 KUNIT_EXPECT_EQ(test, ret, 0);
406 KUNIT_EXPECT_MEMEQ(test,
407 priv->connector.hdmi.vendor,
408 expected_vendor,
409 sizeof(priv->connector.hdmi.vendor));
410}
411
412/*
413 * Test that the registration of a connector with a vendor name larger
414 * than the maximum length fails.
415 */
416static void drm_test_connector_hdmi_init_vendor_length_too_long(struct kunit *test)
417{
418 struct drm_connector_init_priv *priv = test->priv;
419 const char *vendor_name = "VendorVendor";
420 int ret;
421
422 KUNIT_ASSERT_GT(test, strlen(vendor_name), DRM_CONNECTOR_HDMI_VENDOR_LEN);
423
424 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
425 vendor_name, "Product",
426 &dummy_funcs,
427 &dummy_hdmi_funcs,
428 DRM_MODE_CONNECTOR_HDMIA,
429 &priv->ddc,
430 BIT(HDMI_COLORSPACE_RGB),
431 8);
432 KUNIT_EXPECT_LT(test, ret, 0);
433}
434
435/*
436 * Test that the registration of a connector with an invalid maximum bpc
437 * count fails.
438 */
439static void drm_test_connector_hdmi_init_bpc_invalid(struct kunit *test)
440{
441 struct drm_connector_init_priv *priv = test->priv;
442 int ret;
443
444 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
445 "Vendor", "Product",
446 &dummy_funcs,
447 &dummy_hdmi_funcs,
448 DRM_MODE_CONNECTOR_HDMIA,
449 &priv->ddc,
450 BIT(HDMI_COLORSPACE_RGB),
451 9);
452 KUNIT_EXPECT_LT(test, ret, 0);
453}
454
455/*
456 * Test that the registration of a connector with a null maximum bpc
457 * count fails.
458 */
459static void drm_test_connector_hdmi_init_bpc_null(struct kunit *test)
460{
461 struct drm_connector_init_priv *priv = test->priv;
462 int ret;
463
464 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
465 "Vendor", "Product",
466 &dummy_funcs,
467 &dummy_hdmi_funcs,
468 DRM_MODE_CONNECTOR_HDMIA,
469 &priv->ddc,
470 BIT(HDMI_COLORSPACE_RGB),
471 0);
472 KUNIT_EXPECT_LT(test, ret, 0);
473}
474
475/*
476 * Test that the registration of a connector with a maximum bpc count of
477 * 8 succeeds, registers the max bpc property, but doesn't register the
478 * HDR output metadata one.
479 */
480static void drm_test_connector_hdmi_init_bpc_8(struct kunit *test)
481{
482 struct drm_connector_init_priv *priv = test->priv;
483 struct drm_connector_state *state;
484 struct drm_connector *connector = &priv->connector;
485 struct drm_property *prop;
486 uint64_t val;
487 int ret;
488
489 ret = drmm_connector_hdmi_init(&priv->drm, connector,
490 "Vendor", "Product",
491 &dummy_funcs,
492 &dummy_hdmi_funcs,
493 DRM_MODE_CONNECTOR_HDMIA,
494 &priv->ddc,
495 BIT(HDMI_COLORSPACE_RGB),
496 8);
497 KUNIT_EXPECT_EQ(test, ret, 0);
498
499 prop = connector->max_bpc_property;
500 KUNIT_ASSERT_NOT_NULL(test, prop);
501 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
502
503 ret = drm_object_property_get_default_value(&connector->base, prop, &val);
504 KUNIT_EXPECT_EQ(test, ret, 0);
505 KUNIT_EXPECT_EQ(test, val, 8);
506
507 state = connector->state;
508 KUNIT_EXPECT_EQ(test, state->max_bpc, 8);
509 KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 8);
510
511 prop = priv->drm.mode_config.hdr_output_metadata_property;
512 KUNIT_ASSERT_NOT_NULL(test, prop);
513 KUNIT_EXPECT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
514}
515
516/*
517 * Test that the registration of a connector with a maximum bpc count of
518 * 10 succeeds and registers the max bpc and HDR output metadata
519 * properties.
520 */
521static void drm_test_connector_hdmi_init_bpc_10(struct kunit *test)
522{
523 struct drm_connector_init_priv *priv = test->priv;
524 struct drm_connector_state *state;
525 struct drm_connector *connector = &priv->connector;
526 struct drm_property *prop;
527 uint64_t val;
528 int ret;
529
530 ret = drmm_connector_hdmi_init(&priv->drm, connector,
531 "Vendor", "Product",
532 &dummy_funcs,
533 &dummy_hdmi_funcs,
534 DRM_MODE_CONNECTOR_HDMIA,
535 &priv->ddc,
536 BIT(HDMI_COLORSPACE_RGB),
537 10);
538 KUNIT_EXPECT_EQ(test, ret, 0);
539
540 prop = connector->max_bpc_property;
541 KUNIT_ASSERT_NOT_NULL(test, prop);
542 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
543
544 ret = drm_object_property_get_default_value(&connector->base, prop, &val);
545 KUNIT_EXPECT_EQ(test, ret, 0);
546 KUNIT_EXPECT_EQ(test, val, 10);
547
548 state = connector->state;
549 KUNIT_EXPECT_EQ(test, state->max_bpc, 10);
550 KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 10);
551
552 prop = priv->drm.mode_config.hdr_output_metadata_property;
553 KUNIT_ASSERT_NOT_NULL(test, prop);
554 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
555}
556
557/*
558 * Test that the registration of a connector with a maximum bpc count of
559 * 12 succeeds and registers the max bpc and HDR output metadata
560 * properties.
561 */
562static void drm_test_connector_hdmi_init_bpc_12(struct kunit *test)
563{
564 struct drm_connector_init_priv *priv = test->priv;
565 struct drm_connector_state *state;
566 struct drm_connector *connector = &priv->connector;
567 struct drm_property *prop;
568 uint64_t val;
569 int ret;
570
571 ret = drmm_connector_hdmi_init(&priv->drm, connector,
572 "Vendor", "Product",
573 &dummy_funcs,
574 &dummy_hdmi_funcs,
575 DRM_MODE_CONNECTOR_HDMIA,
576 &priv->ddc,
577 BIT(HDMI_COLORSPACE_RGB),
578 12);
579 KUNIT_EXPECT_EQ(test, ret, 0);
580
581 prop = connector->max_bpc_property;
582 KUNIT_ASSERT_NOT_NULL(test, prop);
583 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
584
585 ret = drm_object_property_get_default_value(&connector->base, prop, &val);
586 KUNIT_EXPECT_EQ(test, ret, 0);
587 KUNIT_EXPECT_EQ(test, val, 12);
588
589 state = connector->state;
590 KUNIT_EXPECT_EQ(test, state->max_bpc, 12);
591 KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 12);
592
593 prop = priv->drm.mode_config.hdr_output_metadata_property;
594 KUNIT_ASSERT_NOT_NULL(test, prop);
595 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
596}
597
598/*
599 * Test that the registration of an HDMI connector with no supported
600 * format fails.
601 */
602static void drm_test_connector_hdmi_init_formats_empty(struct kunit *test)
603{
604 struct drm_connector_init_priv *priv = test->priv;
605 int ret;
606
607 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
608 "Vendor", "Product",
609 &dummy_funcs,
610 &dummy_hdmi_funcs,
611 DRM_MODE_CONNECTOR_HDMIA,
612 &priv->ddc,
613 0,
614 8);
615 KUNIT_EXPECT_LT(test, ret, 0);
616}
617
618/*
619 * Test that the registration of an HDMI connector not listing RGB as a
620 * supported format fails.
621 */
622static void drm_test_connector_hdmi_init_formats_no_rgb(struct kunit *test)
623{
624 struct drm_connector_init_priv *priv = test->priv;
625 int ret;
626
627 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
628 "Vendor", "Product",
629 &dummy_funcs,
630 &dummy_hdmi_funcs,
631 DRM_MODE_CONNECTOR_HDMIA,
632 &priv->ddc,
633 BIT(HDMI_COLORSPACE_YUV422),
634 8);
635 KUNIT_EXPECT_LT(test, ret, 0);
636}
637
638struct drm_connector_hdmi_init_formats_yuv420_allowed_test {
639 unsigned long supported_formats;
640 bool yuv420_allowed;
641 int expected_result;
642};
643
644#define YUV420_ALLOWED_TEST(_formats, _allowed, _result) \
645 { \
646 .supported_formats = BIT(HDMI_COLORSPACE_RGB) | (_formats), \
647 .yuv420_allowed = _allowed, \
648 .expected_result = _result, \
649 }
650
651static const struct drm_connector_hdmi_init_formats_yuv420_allowed_test
652drm_connector_hdmi_init_formats_yuv420_allowed_tests[] = {
653 YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV420), true, 0),
654 YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV420), false, -EINVAL),
655 YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV422), true, -EINVAL),
656 YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV422), false, 0),
657};
658
659static void
660drm_connector_hdmi_init_formats_yuv420_allowed_desc(const struct drm_connector_hdmi_init_formats_yuv420_allowed_test *t,
661 char *desc)
662{
663 sprintf(desc, "supported_formats=0x%lx yuv420_allowed=%d",
664 t->supported_formats, t->yuv420_allowed);
665}
666
667KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_formats_yuv420_allowed,
668 drm_connector_hdmi_init_formats_yuv420_allowed_tests,
669 drm_connector_hdmi_init_formats_yuv420_allowed_desc);
670
671/*
672 * Test that the registration of an HDMI connector succeeds only when
673 * the presence of YUV420 in the supported formats matches the value
674 * of the ycbcr_420_allowed flag.
675 */
676static void drm_test_connector_hdmi_init_formats_yuv420_allowed(struct kunit *test)
677{
678 const struct drm_connector_hdmi_init_formats_yuv420_allowed_test *params;
679 struct drm_connector_init_priv *priv = test->priv;
680 int ret;
681
682 params = test->param_value;
683 priv->connector.ycbcr_420_allowed = params->yuv420_allowed;
684
685 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
686 "Vendor", "Product",
687 &dummy_funcs,
688 &dummy_hdmi_funcs,
689 DRM_MODE_CONNECTOR_HDMIA,
690 &priv->ddc,
691 params->supported_formats,
692 8);
693 KUNIT_EXPECT_EQ(test, ret, params->expected_result);
694}
695
696/*
697 * Test that the registration of an HDMI connector with an HDMI
698 * connector type succeeds.
699 */
700static void drm_test_connector_hdmi_init_type_valid(struct kunit *test)
701{
702 struct drm_connector_init_priv *priv = test->priv;
703 unsigned int connector_type = *(unsigned int *)test->param_value;
704 int ret;
705
706 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
707 "Vendor", "Product",
708 &dummy_funcs,
709 &dummy_hdmi_funcs,
710 connector_type,
711 &priv->ddc,
712 BIT(HDMI_COLORSPACE_RGB),
713 8);
714 KUNIT_EXPECT_EQ(test, ret, 0);
715}
716
717static const unsigned int drm_connector_hdmi_init_type_valid_tests[] = {
718 DRM_MODE_CONNECTOR_HDMIA,
719 DRM_MODE_CONNECTOR_HDMIB,
720};
721
722static void drm_connector_hdmi_init_type_desc(const unsigned int *type, char *desc)
723{
724 sprintf(desc, "%s", drm_get_connector_type_name(*type));
725}
726
727KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_valid,
728 drm_connector_hdmi_init_type_valid_tests,
729 drm_connector_hdmi_init_type_desc);
730
731/*
732 * Test that the registration of an HDMI connector with an !HDMI
733 * connector type fails.
734 */
735static void drm_test_connector_hdmi_init_type_invalid(struct kunit *test)
736{
737 struct drm_connector_init_priv *priv = test->priv;
738 unsigned int connector_type = *(unsigned int *)test->param_value;
739 int ret;
740
741 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
742 "Vendor", "Product",
743 &dummy_funcs,
744 &dummy_hdmi_funcs,
745 connector_type,
746 &priv->ddc,
747 BIT(HDMI_COLORSPACE_RGB),
748 8);
749 KUNIT_EXPECT_LT(test, ret, 0);
750}
751
752static const unsigned int drm_connector_hdmi_init_type_invalid_tests[] = {
753 DRM_MODE_CONNECTOR_Unknown,
754 DRM_MODE_CONNECTOR_VGA,
755 DRM_MODE_CONNECTOR_DVII,
756 DRM_MODE_CONNECTOR_DVID,
757 DRM_MODE_CONNECTOR_DVIA,
758 DRM_MODE_CONNECTOR_Composite,
759 DRM_MODE_CONNECTOR_SVIDEO,
760 DRM_MODE_CONNECTOR_LVDS,
761 DRM_MODE_CONNECTOR_Component,
762 DRM_MODE_CONNECTOR_9PinDIN,
763 DRM_MODE_CONNECTOR_DisplayPort,
764 DRM_MODE_CONNECTOR_TV,
765 DRM_MODE_CONNECTOR_eDP,
766 DRM_MODE_CONNECTOR_VIRTUAL,
767 DRM_MODE_CONNECTOR_DSI,
768 DRM_MODE_CONNECTOR_DPI,
769 DRM_MODE_CONNECTOR_WRITEBACK,
770 DRM_MODE_CONNECTOR_SPI,
771 DRM_MODE_CONNECTOR_USB,
772};
773
774KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_invalid,
775 drm_connector_hdmi_init_type_invalid_tests,
776 drm_connector_hdmi_init_type_desc);
777
778static struct kunit_case drmm_connector_hdmi_init_tests[] = {
779 KUNIT_CASE(drm_test_connector_hdmi_init_valid),
780 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_8),
781 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_10),
782 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_12),
783 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_invalid),
784 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_null),
785 KUNIT_CASE(drm_test_connector_hdmi_init_formats_empty),
786 KUNIT_CASE(drm_test_connector_hdmi_init_formats_no_rgb),
787 KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_formats_yuv420_allowed,
788 drm_connector_hdmi_init_formats_yuv420_allowed_gen_params),
789 KUNIT_CASE(drm_test_connector_hdmi_init_null_ddc),
790 KUNIT_CASE(drm_test_connector_hdmi_init_null_product),
791 KUNIT_CASE(drm_test_connector_hdmi_init_null_vendor),
792 KUNIT_CASE(drm_test_connector_hdmi_init_product_length_exact),
793 KUNIT_CASE(drm_test_connector_hdmi_init_product_length_too_long),
794 KUNIT_CASE(drm_test_connector_hdmi_init_product_valid),
795 KUNIT_CASE(drm_test_connector_hdmi_init_vendor_length_exact),
796 KUNIT_CASE(drm_test_connector_hdmi_init_vendor_length_too_long),
797 KUNIT_CASE(drm_test_connector_hdmi_init_vendor_valid),
798 KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_valid,
799 drm_connector_hdmi_init_type_valid_gen_params),
800 KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_invalid,
801 drm_connector_hdmi_init_type_invalid_gen_params),
802 { }
803};
804
805static struct kunit_suite drmm_connector_hdmi_init_test_suite = {
806 .name = "drmm_connector_hdmi_init",
807 .init = drm_test_connector_init,
808 .test_cases = drmm_connector_hdmi_init_tests,
809};
810
811struct drm_get_tv_mode_from_name_test {
812 const char *name;
813 enum drm_connector_tv_mode expected_mode;
814};
815
816#define TV_MODE_NAME(_name, _mode) \
817 { \
818 .name = _name, \
819 .expected_mode = _mode, \
820 }
821
822static void drm_test_get_tv_mode_from_name_valid(struct kunit *test)
823{
824 const struct drm_get_tv_mode_from_name_test *params = test->param_value;
825
826 KUNIT_EXPECT_EQ(test,
827 drm_get_tv_mode_from_name(params->name, strlen(params->name)),
828 params->expected_mode);
829}
830
831static const
832struct drm_get_tv_mode_from_name_test drm_get_tv_mode_from_name_valid_tests[] = {
833 TV_MODE_NAME("NTSC", DRM_MODE_TV_MODE_NTSC),
834 TV_MODE_NAME("NTSC-443", DRM_MODE_TV_MODE_NTSC_443),
835 TV_MODE_NAME("NTSC-J", DRM_MODE_TV_MODE_NTSC_J),
836 TV_MODE_NAME("PAL", DRM_MODE_TV_MODE_PAL),
837 TV_MODE_NAME("PAL-M", DRM_MODE_TV_MODE_PAL_M),
838 TV_MODE_NAME("PAL-N", DRM_MODE_TV_MODE_PAL_N),
839 TV_MODE_NAME("SECAM", DRM_MODE_TV_MODE_SECAM),
840 TV_MODE_NAME("Mono", DRM_MODE_TV_MODE_MONOCHROME),
841};
842
843static void
844drm_get_tv_mode_from_name_valid_desc(const struct drm_get_tv_mode_from_name_test *t,
845 char *desc)
846{
847 sprintf(desc, "%s", t->name);
848}
849
850KUNIT_ARRAY_PARAM(drm_get_tv_mode_from_name_valid,
851 drm_get_tv_mode_from_name_valid_tests,
852 drm_get_tv_mode_from_name_valid_desc);
853
854static void drm_test_get_tv_mode_from_name_truncated(struct kunit *test)
855{
856 const char *name = "NTS";
857 int ret;
858
859 ret = drm_get_tv_mode_from_name(name, strlen(name));
860 KUNIT_EXPECT_LT(test, ret, 0);
861};
862
863static struct kunit_case drm_get_tv_mode_from_name_tests[] = {
864 KUNIT_CASE_PARAM(drm_test_get_tv_mode_from_name_valid,
865 drm_get_tv_mode_from_name_valid_gen_params),
866 KUNIT_CASE(drm_test_get_tv_mode_from_name_truncated),
867 { }
868};
869
870static struct kunit_suite drm_get_tv_mode_from_name_test_suite = {
871 .name = "drm_get_tv_mode_from_name",
872 .test_cases = drm_get_tv_mode_from_name_tests,
873};
874
875struct drm_hdmi_connector_get_broadcast_rgb_name_test {
876 unsigned int kind;
877 const char *expected_name;
878};
879
880#define BROADCAST_RGB_TEST(_kind, _name) \
881 { \
882 .kind = _kind, \
883 .expected_name = _name, \
884 }
885
886static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name(struct kunit *test)
887{
888 const struct drm_hdmi_connector_get_broadcast_rgb_name_test *params =
889 test->param_value;
890
891 KUNIT_EXPECT_STREQ(test,
892 drm_hdmi_connector_get_broadcast_rgb_name(params->kind),
893 params->expected_name);
894}
895
896static const
897struct drm_hdmi_connector_get_broadcast_rgb_name_test
898drm_hdmi_connector_get_broadcast_rgb_name_valid_tests[] = {
899 BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic"),
900 BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_FULL, "Full"),
901 BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235"),
902};
903
904static void
905drm_hdmi_connector_get_broadcast_rgb_name_valid_desc(const struct drm_hdmi_connector_get_broadcast_rgb_name_test *t,
906 char *desc)
907{
908 sprintf(desc, "%s", t->expected_name);
909}
910
911KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_broadcast_rgb_name_valid,
912 drm_hdmi_connector_get_broadcast_rgb_name_valid_tests,
913 drm_hdmi_connector_get_broadcast_rgb_name_valid_desc);
914
915static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid(struct kunit *test)
916{
917 KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_broadcast_rgb_name(3));
918};
919
920static struct kunit_case drm_hdmi_connector_get_broadcast_rgb_name_tests[] = {
921 KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_broadcast_rgb_name,
922 drm_hdmi_connector_get_broadcast_rgb_name_valid_gen_params),
923 KUNIT_CASE(drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid),
924 { }
925};
926
927static struct kunit_suite drm_hdmi_connector_get_broadcast_rgb_name_test_suite = {
928 .name = "drm_hdmi_connector_get_broadcast_rgb_name",
929 .test_cases = drm_hdmi_connector_get_broadcast_rgb_name_tests,
930};
931
932struct drm_hdmi_connector_get_output_format_name_test {
933 unsigned int kind;
934 const char *expected_name;
935};
936
937#define OUTPUT_FORMAT_TEST(_kind, _name) \
938 { \
939 .kind = _kind, \
940 .expected_name = _name, \
941 }
942
943static void drm_test_drm_hdmi_connector_get_output_format_name(struct kunit *test)
944{
945 const struct drm_hdmi_connector_get_output_format_name_test *params =
946 test->param_value;
947
948 KUNIT_EXPECT_STREQ(test,
949 drm_hdmi_connector_get_output_format_name(params->kind),
950 params->expected_name);
951}
952
953static const
954struct drm_hdmi_connector_get_output_format_name_test
955drm_hdmi_connector_get_output_format_name_valid_tests[] = {
956 OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_RGB, "RGB"),
957 OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV420, "YUV 4:2:0"),
958 OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV422, "YUV 4:2:2"),
959 OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV444, "YUV 4:4:4"),
960};
961
962static void
963drm_hdmi_connector_get_output_format_name_valid_desc(const struct drm_hdmi_connector_get_output_format_name_test *t,
964 char *desc)
965{
966 sprintf(desc, "%s", t->expected_name);
967}
968
969KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_output_format_name_valid,
970 drm_hdmi_connector_get_output_format_name_valid_tests,
971 drm_hdmi_connector_get_output_format_name_valid_desc);
972
973static void drm_test_drm_hdmi_connector_get_output_format_name_invalid(struct kunit *test)
974{
975 KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_output_format_name(4));
976};
977
978static struct kunit_case drm_hdmi_connector_get_output_format_name_tests[] = {
979 KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_output_format_name,
980 drm_hdmi_connector_get_output_format_name_valid_gen_params),
981 KUNIT_CASE(drm_test_drm_hdmi_connector_get_output_format_name_invalid),
982 { }
983};
984
985static struct kunit_suite drm_hdmi_connector_get_output_format_name_test_suite = {
986 .name = "drm_hdmi_connector_get_output_format_name",
987 .test_cases = drm_hdmi_connector_get_output_format_name_tests,
988};
989
990static void drm_test_drm_connector_attach_broadcast_rgb_property(struct kunit *test)
991{
992 struct drm_connector_init_priv *priv = test->priv;
993 struct drm_connector *connector = &priv->connector;
994 struct drm_property *prop;
995 int ret;
996
997 ret = drmm_connector_init(&priv->drm, connector,
998 &dummy_funcs,
999 DRM_MODE_CONNECTOR_HDMIA,
1000 &priv->ddc);
1001 KUNIT_ASSERT_EQ(test, ret, 0);
1002
1003 ret = drm_connector_attach_broadcast_rgb_property(connector);
1004 KUNIT_ASSERT_EQ(test, ret, 0);
1005
1006 prop = connector->broadcast_rgb_property;
1007 KUNIT_ASSERT_NOT_NULL(test, prop);
1008 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
1009}
1010
1011static void drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(struct kunit *test)
1012{
1013 struct drm_connector_init_priv *priv = test->priv;
1014 struct drm_connector *connector = &priv->connector;
1015 struct drm_property *prop;
1016 int ret;
1017
1018 ret = drmm_connector_hdmi_init(&priv->drm, connector,
1019 "Vendor", "Product",
1020 &dummy_funcs,
1021 &dummy_hdmi_funcs,
1022 DRM_MODE_CONNECTOR_HDMIA,
1023 &priv->ddc,
1024 BIT(HDMI_COLORSPACE_RGB),
1025 8);
1026 KUNIT_EXPECT_EQ(test, ret, 0);
1027
1028 ret = drm_connector_attach_broadcast_rgb_property(connector);
1029 KUNIT_ASSERT_EQ(test, ret, 0);
1030
1031 prop = connector->broadcast_rgb_property;
1032 KUNIT_ASSERT_NOT_NULL(test, prop);
1033 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
1034}
1035
1036static struct kunit_case drm_connector_attach_broadcast_rgb_property_tests[] = {
1037 KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property),
1038 KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector),
1039 { }
1040};
1041
1042static struct kunit_suite drm_connector_attach_broadcast_rgb_property_test_suite = {
1043 .name = "drm_connector_attach_broadcast_rgb_property",
1044 .init = drm_test_connector_init,
1045 .test_cases = drm_connector_attach_broadcast_rgb_property_tests,
1046};
1047
1048/*
1049 * Test that for a given mode, with 8bpc and an RGB output the TMDS
1050 * character rate is equal to the mode pixel clock.
1051 */
1052static void drm_test_drm_hdmi_compute_mode_clock_rgb(struct kunit *test)
1053{
1054 struct drm_connector_init_priv *priv = test->priv;
1055 const struct drm_display_mode *mode;
1056 unsigned long long rate;
1057 struct drm_device *drm = &priv->drm;
1058
1059 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1060 KUNIT_ASSERT_NOT_NULL(test, mode);
1061
1062 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1063
1064 rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
1065 KUNIT_ASSERT_GT(test, rate, 0);
1066 KUNIT_EXPECT_EQ(test, mode->clock * 1000ULL, rate);
1067}
1068
1069/*
1070 * Test that for a given mode, with 10bpc and an RGB output the TMDS
1071 * character rate is equal to 1.25 times the mode pixel clock.
1072 */
1073static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc(struct kunit *test)
1074{
1075 struct drm_connector_init_priv *priv = test->priv;
1076 const struct drm_display_mode *mode;
1077 unsigned long long rate;
1078 struct drm_device *drm = &priv->drm;
1079
1080 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1081 KUNIT_ASSERT_NOT_NULL(test, mode);
1082
1083 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1084
1085 rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
1086 KUNIT_ASSERT_GT(test, rate, 0);
1087 KUNIT_EXPECT_EQ(test, mode->clock * 1250, rate);
1088}
1089
1090/*
1091 * Test that for the VIC-1 mode, with 10bpc and an RGB output the TMDS
1092 * character rate computation fails.
1093 */
1094static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1(struct kunit *test)
1095{
1096 struct drm_connector_init_priv *priv = test->priv;
1097 const struct drm_display_mode *mode;
1098 unsigned long long rate;
1099 struct drm_device *drm = &priv->drm;
1100
1101 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
1102 KUNIT_ASSERT_NOT_NULL(test, mode);
1103
1104 rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
1105 KUNIT_EXPECT_EQ(test, rate, 0);
1106}
1107
1108/*
1109 * Test that for a given mode, with 12bpc and an RGB output the TMDS
1110 * character rate is equal to 1.5 times the mode pixel clock.
1111 */
1112static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc(struct kunit *test)
1113{
1114 struct drm_connector_init_priv *priv = test->priv;
1115 const struct drm_display_mode *mode;
1116 unsigned long long rate;
1117 struct drm_device *drm = &priv->drm;
1118
1119 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1120 KUNIT_ASSERT_NOT_NULL(test, mode);
1121
1122 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1123
1124 rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
1125 KUNIT_ASSERT_GT(test, rate, 0);
1126 KUNIT_EXPECT_EQ(test, mode->clock * 1500, rate);
1127}
1128
1129/*
1130 * Test that for the VIC-1 mode, with 12bpc and an RGB output the TMDS
1131 * character rate computation fails.
1132 */
1133static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1(struct kunit *test)
1134{
1135 struct drm_connector_init_priv *priv = test->priv;
1136 const struct drm_display_mode *mode;
1137 unsigned long long rate;
1138 struct drm_device *drm = &priv->drm;
1139
1140 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
1141 KUNIT_ASSERT_NOT_NULL(test, mode);
1142
1143 rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
1144 KUNIT_EXPECT_EQ(test, rate, 0);
1145}
1146
1147/*
1148 * Test that for a mode with the pixel repetition flag, the TMDS
1149 * character rate is indeed double the mode pixel clock.
1150 */
1151static void drm_test_drm_hdmi_compute_mode_clock_rgb_double(struct kunit *test)
1152{
1153 struct drm_connector_init_priv *priv = test->priv;
1154 const struct drm_display_mode *mode;
1155 unsigned long long rate;
1156 struct drm_device *drm = &priv->drm;
1157
1158 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 6);
1159 KUNIT_ASSERT_NOT_NULL(test, mode);
1160
1161 KUNIT_ASSERT_TRUE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1162
1163 rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
1164 KUNIT_ASSERT_GT(test, rate, 0);
1165 KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) * 2, rate);
1166}
1167
1168/*
1169 * Test that the TMDS character rate computation for the VIC modes
1170 * explicitly listed in the spec as supporting YUV420 succeed and return
1171 * half the mode pixel clock.
1172 */
1173static void drm_test_connector_hdmi_compute_mode_clock_yuv420_valid(struct kunit *test)
1174{
1175 struct drm_connector_init_priv *priv = test->priv;
1176 const struct drm_display_mode *mode;
1177 struct drm_device *drm = &priv->drm;
1178 unsigned long long rate;
1179 unsigned int vic = *(unsigned int *)test->param_value;
1180
1181 mode = drm_kunit_display_mode_from_cea_vic(test, drm, vic);
1182 KUNIT_ASSERT_NOT_NULL(test, mode);
1183
1184 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1185
1186 rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV420);
1187 KUNIT_ASSERT_GT(test, rate, 0);
1188 KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) / 2, rate);
1189}
1190
1191static const unsigned int drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[] = {
1192 96, 97, 101, 102, 106, 107,
1193};
1194
1195static void drm_hdmi_compute_mode_clock_yuv420_vic_desc(const unsigned int *vic, char *desc)
1196{
1197 sprintf(desc, "VIC %u", *vic);
1198}
1199
1200KUNIT_ARRAY_PARAM(drm_hdmi_compute_mode_clock_yuv420_valid,
1201 drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests,
1202 drm_hdmi_compute_mode_clock_yuv420_vic_desc);
1203
1204/*
1205 * Test that for a given mode listed supporting it and an YUV420 output
1206 * with 10bpc, the TMDS character rate is equal to 0.625 times the mode
1207 * pixel clock.
1208 */
1209static void drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc(struct kunit *test)
1210{
1211 struct drm_connector_init_priv *priv = test->priv;
1212 const struct drm_display_mode *mode;
1213 struct drm_device *drm = &priv->drm;
1214 unsigned int vic =
1215 drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0];
1216 unsigned long long rate;
1217
1218 mode = drm_kunit_display_mode_from_cea_vic(test, drm, vic);
1219 KUNIT_ASSERT_NOT_NULL(test, mode);
1220
1221 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1222
1223 rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV420);
1224 KUNIT_ASSERT_GT(test, rate, 0);
1225
1226 KUNIT_EXPECT_EQ(test, mode->clock * 625, rate);
1227}
1228
1229/*
1230 * Test that for a given mode listed supporting it and an YUV420 output
1231 * with 12bpc, the TMDS character rate is equal to 0.75 times the mode
1232 * pixel clock.
1233 */
1234static void drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc(struct kunit *test)
1235{
1236 struct drm_connector_init_priv *priv = test->priv;
1237 const struct drm_display_mode *mode;
1238 struct drm_device *drm = &priv->drm;
1239 unsigned int vic =
1240 drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0];
1241 unsigned long long rate;
1242
1243 mode = drm_kunit_display_mode_from_cea_vic(test, drm, vic);
1244 KUNIT_ASSERT_NOT_NULL(test, mode);
1245
1246 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1247
1248 rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV420);
1249 KUNIT_ASSERT_GT(test, rate, 0);
1250
1251 KUNIT_EXPECT_EQ(test, mode->clock * 750, rate);
1252}
1253
1254/*
1255 * Test that for a given mode, the computation of the TMDS character
1256 * rate with 8bpc and a YUV422 output succeeds and returns a rate equal
1257 * to the mode pixel clock.
1258 */
1259static void drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc(struct kunit *test)
1260{
1261 struct drm_connector_init_priv *priv = test->priv;
1262 const struct drm_display_mode *mode;
1263 struct drm_device *drm = &priv->drm;
1264 unsigned long long rate;
1265
1266 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1267 KUNIT_ASSERT_NOT_NULL(test, mode);
1268
1269 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1270
1271 rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV422);
1272 KUNIT_ASSERT_GT(test, rate, 0);
1273 KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1274}
1275
1276/*
1277 * Test that for a given mode, the computation of the TMDS character
1278 * rate with 10bpc and a YUV422 output succeeds and returns a rate equal
1279 * to the mode pixel clock.
1280 */
1281static void drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc(struct kunit *test)
1282{
1283 struct drm_connector_init_priv *priv = test->priv;
1284 const struct drm_display_mode *mode;
1285 struct drm_device *drm = &priv->drm;
1286 unsigned long long rate;
1287
1288 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1289 KUNIT_ASSERT_NOT_NULL(test, mode);
1290
1291 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1292
1293 rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV422);
1294 KUNIT_ASSERT_GT(test, rate, 0);
1295 KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1296}
1297
1298/*
1299 * Test that for a given mode, the computation of the TMDS character
1300 * rate with 12bpc and a YUV422 output succeeds and returns a rate equal
1301 * to the mode pixel clock.
1302 */
1303static void drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc(struct kunit *test)
1304{
1305 struct drm_connector_init_priv *priv = test->priv;
1306 const struct drm_display_mode *mode;
1307 struct drm_device *drm = &priv->drm;
1308 unsigned long long rate;
1309
1310 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1311 KUNIT_ASSERT_NOT_NULL(test, mode);
1312
1313 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1314
1315 rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV422);
1316 KUNIT_ASSERT_GT(test, rate, 0);
1317 KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1318}
1319
1320static struct kunit_case drm_hdmi_compute_mode_clock_tests[] = {
1321 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb),
1322 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc),
1323 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1),
1324 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc),
1325 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1),
1326 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_double),
1327 KUNIT_CASE_PARAM(drm_test_connector_hdmi_compute_mode_clock_yuv420_valid,
1328 drm_hdmi_compute_mode_clock_yuv420_valid_gen_params),
1329 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc),
1330 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc),
1331 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc),
1332 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc),
1333 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc),
1334 { }
1335};
1336
1337static struct kunit_suite drm_hdmi_compute_mode_clock_test_suite = {
1338 .name = "drm_test_connector_hdmi_compute_mode_clock",
1339 .init = drm_test_connector_init,
1340 .test_cases = drm_hdmi_compute_mode_clock_tests,
1341};
1342
1343kunit_test_suites(
1344 &drmm_connector_hdmi_init_test_suite,
1345 &drmm_connector_init_test_suite,
1346 &drm_connector_attach_broadcast_rgb_property_test_suite,
1347 &drm_get_tv_mode_from_name_test_suite,
1348 &drm_hdmi_compute_mode_clock_test_suite,
1349 &drm_hdmi_connector_get_broadcast_rgb_name_test_suite,
1350 &drm_hdmi_connector_get_output_format_name_test_suite
1351);
1352
1353MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
1354MODULE_DESCRIPTION("Kunit test for drm_modes functions");
1355MODULE_LICENSE("GPL");