Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
638/*
639 * Test that the registration of an HDMI connector with an HDMI
640 * connector type succeeds.
641 */
642static void drm_test_connector_hdmi_init_type_valid(struct kunit *test)
643{
644 struct drm_connector_init_priv *priv = test->priv;
645 unsigned int connector_type = *(unsigned int *)test->param_value;
646 int ret;
647
648 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
649 "Vendor", "Product",
650 &dummy_funcs,
651 &dummy_hdmi_funcs,
652 connector_type,
653 &priv->ddc,
654 BIT(HDMI_COLORSPACE_RGB),
655 8);
656 KUNIT_EXPECT_EQ(test, ret, 0);
657}
658
659static const unsigned int drm_connector_hdmi_init_type_valid_tests[] = {
660 DRM_MODE_CONNECTOR_HDMIA,
661 DRM_MODE_CONNECTOR_HDMIB,
662};
663
664static void drm_connector_hdmi_init_type_desc(const unsigned int *type, char *desc)
665{
666 sprintf(desc, "%s", drm_get_connector_type_name(*type));
667}
668
669KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_valid,
670 drm_connector_hdmi_init_type_valid_tests,
671 drm_connector_hdmi_init_type_desc);
672
673/*
674 * Test that the registration of an HDMI connector with an !HDMI
675 * connector type fails.
676 */
677static void drm_test_connector_hdmi_init_type_invalid(struct kunit *test)
678{
679 struct drm_connector_init_priv *priv = test->priv;
680 unsigned int connector_type = *(unsigned int *)test->param_value;
681 int ret;
682
683 ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
684 "Vendor", "Product",
685 &dummy_funcs,
686 &dummy_hdmi_funcs,
687 connector_type,
688 &priv->ddc,
689 BIT(HDMI_COLORSPACE_RGB),
690 8);
691 KUNIT_EXPECT_LT(test, ret, 0);
692}
693
694static const unsigned int drm_connector_hdmi_init_type_invalid_tests[] = {
695 DRM_MODE_CONNECTOR_Unknown,
696 DRM_MODE_CONNECTOR_VGA,
697 DRM_MODE_CONNECTOR_DVII,
698 DRM_MODE_CONNECTOR_DVID,
699 DRM_MODE_CONNECTOR_DVIA,
700 DRM_MODE_CONNECTOR_Composite,
701 DRM_MODE_CONNECTOR_SVIDEO,
702 DRM_MODE_CONNECTOR_LVDS,
703 DRM_MODE_CONNECTOR_Component,
704 DRM_MODE_CONNECTOR_9PinDIN,
705 DRM_MODE_CONNECTOR_DisplayPort,
706 DRM_MODE_CONNECTOR_TV,
707 DRM_MODE_CONNECTOR_eDP,
708 DRM_MODE_CONNECTOR_VIRTUAL,
709 DRM_MODE_CONNECTOR_DSI,
710 DRM_MODE_CONNECTOR_DPI,
711 DRM_MODE_CONNECTOR_WRITEBACK,
712 DRM_MODE_CONNECTOR_SPI,
713 DRM_MODE_CONNECTOR_USB,
714};
715
716KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_invalid,
717 drm_connector_hdmi_init_type_invalid_tests,
718 drm_connector_hdmi_init_type_desc);
719
720static struct kunit_case drmm_connector_hdmi_init_tests[] = {
721 KUNIT_CASE(drm_test_connector_hdmi_init_valid),
722 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_8),
723 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_10),
724 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_12),
725 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_invalid),
726 KUNIT_CASE(drm_test_connector_hdmi_init_bpc_null),
727 KUNIT_CASE(drm_test_connector_hdmi_init_formats_empty),
728 KUNIT_CASE(drm_test_connector_hdmi_init_formats_no_rgb),
729 KUNIT_CASE(drm_test_connector_hdmi_init_null_ddc),
730 KUNIT_CASE(drm_test_connector_hdmi_init_null_product),
731 KUNIT_CASE(drm_test_connector_hdmi_init_null_vendor),
732 KUNIT_CASE(drm_test_connector_hdmi_init_product_length_exact),
733 KUNIT_CASE(drm_test_connector_hdmi_init_product_length_too_long),
734 KUNIT_CASE(drm_test_connector_hdmi_init_product_valid),
735 KUNIT_CASE(drm_test_connector_hdmi_init_vendor_length_exact),
736 KUNIT_CASE(drm_test_connector_hdmi_init_vendor_length_too_long),
737 KUNIT_CASE(drm_test_connector_hdmi_init_vendor_valid),
738 KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_valid,
739 drm_connector_hdmi_init_type_valid_gen_params),
740 KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_invalid,
741 drm_connector_hdmi_init_type_invalid_gen_params),
742 { }
743};
744
745static struct kunit_suite drmm_connector_hdmi_init_test_suite = {
746 .name = "drmm_connector_hdmi_init",
747 .init = drm_test_connector_init,
748 .test_cases = drmm_connector_hdmi_init_tests,
749};
750
751struct drm_get_tv_mode_from_name_test {
752 const char *name;
753 enum drm_connector_tv_mode expected_mode;
754};
755
756#define TV_MODE_NAME(_name, _mode) \
757 { \
758 .name = _name, \
759 .expected_mode = _mode, \
760 }
761
762static void drm_test_get_tv_mode_from_name_valid(struct kunit *test)
763{
764 const struct drm_get_tv_mode_from_name_test *params = test->param_value;
765
766 KUNIT_EXPECT_EQ(test,
767 drm_get_tv_mode_from_name(params->name, strlen(params->name)),
768 params->expected_mode);
769}
770
771static const
772struct drm_get_tv_mode_from_name_test drm_get_tv_mode_from_name_valid_tests[] = {
773 TV_MODE_NAME("NTSC", DRM_MODE_TV_MODE_NTSC),
774 TV_MODE_NAME("NTSC-443", DRM_MODE_TV_MODE_NTSC_443),
775 TV_MODE_NAME("NTSC-J", DRM_MODE_TV_MODE_NTSC_J),
776 TV_MODE_NAME("PAL", DRM_MODE_TV_MODE_PAL),
777 TV_MODE_NAME("PAL-M", DRM_MODE_TV_MODE_PAL_M),
778 TV_MODE_NAME("PAL-N", DRM_MODE_TV_MODE_PAL_N),
779 TV_MODE_NAME("SECAM", DRM_MODE_TV_MODE_SECAM),
780 TV_MODE_NAME("Mono", DRM_MODE_TV_MODE_MONOCHROME),
781};
782
783static void
784drm_get_tv_mode_from_name_valid_desc(const struct drm_get_tv_mode_from_name_test *t,
785 char *desc)
786{
787 sprintf(desc, "%s", t->name);
788}
789
790KUNIT_ARRAY_PARAM(drm_get_tv_mode_from_name_valid,
791 drm_get_tv_mode_from_name_valid_tests,
792 drm_get_tv_mode_from_name_valid_desc);
793
794static void drm_test_get_tv_mode_from_name_truncated(struct kunit *test)
795{
796 const char *name = "NTS";
797 int ret;
798
799 ret = drm_get_tv_mode_from_name(name, strlen(name));
800 KUNIT_EXPECT_LT(test, ret, 0);
801};
802
803static struct kunit_case drm_get_tv_mode_from_name_tests[] = {
804 KUNIT_CASE_PARAM(drm_test_get_tv_mode_from_name_valid,
805 drm_get_tv_mode_from_name_valid_gen_params),
806 KUNIT_CASE(drm_test_get_tv_mode_from_name_truncated),
807 { }
808};
809
810static struct kunit_suite drm_get_tv_mode_from_name_test_suite = {
811 .name = "drm_get_tv_mode_from_name",
812 .test_cases = drm_get_tv_mode_from_name_tests,
813};
814
815struct drm_hdmi_connector_get_broadcast_rgb_name_test {
816 unsigned int kind;
817 const char *expected_name;
818};
819
820#define BROADCAST_RGB_TEST(_kind, _name) \
821 { \
822 .kind = _kind, \
823 .expected_name = _name, \
824 }
825
826static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name(struct kunit *test)
827{
828 const struct drm_hdmi_connector_get_broadcast_rgb_name_test *params =
829 test->param_value;
830
831 KUNIT_EXPECT_STREQ(test,
832 drm_hdmi_connector_get_broadcast_rgb_name(params->kind),
833 params->expected_name);
834}
835
836static const
837struct drm_hdmi_connector_get_broadcast_rgb_name_test
838drm_hdmi_connector_get_broadcast_rgb_name_valid_tests[] = {
839 BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic"),
840 BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_FULL, "Full"),
841 BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235"),
842};
843
844static void
845drm_hdmi_connector_get_broadcast_rgb_name_valid_desc(const struct drm_hdmi_connector_get_broadcast_rgb_name_test *t,
846 char *desc)
847{
848 sprintf(desc, "%s", t->expected_name);
849}
850
851KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_broadcast_rgb_name_valid,
852 drm_hdmi_connector_get_broadcast_rgb_name_valid_tests,
853 drm_hdmi_connector_get_broadcast_rgb_name_valid_desc);
854
855static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid(struct kunit *test)
856{
857 KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_broadcast_rgb_name(3));
858};
859
860static struct kunit_case drm_hdmi_connector_get_broadcast_rgb_name_tests[] = {
861 KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_broadcast_rgb_name,
862 drm_hdmi_connector_get_broadcast_rgb_name_valid_gen_params),
863 KUNIT_CASE(drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid),
864 { }
865};
866
867static struct kunit_suite drm_hdmi_connector_get_broadcast_rgb_name_test_suite = {
868 .name = "drm_hdmi_connector_get_broadcast_rgb_name",
869 .test_cases = drm_hdmi_connector_get_broadcast_rgb_name_tests,
870};
871
872struct drm_hdmi_connector_get_output_format_name_test {
873 unsigned int kind;
874 const char *expected_name;
875};
876
877#define OUTPUT_FORMAT_TEST(_kind, _name) \
878 { \
879 .kind = _kind, \
880 .expected_name = _name, \
881 }
882
883static void drm_test_drm_hdmi_connector_get_output_format_name(struct kunit *test)
884{
885 const struct drm_hdmi_connector_get_output_format_name_test *params =
886 test->param_value;
887
888 KUNIT_EXPECT_STREQ(test,
889 drm_hdmi_connector_get_output_format_name(params->kind),
890 params->expected_name);
891}
892
893static const
894struct drm_hdmi_connector_get_output_format_name_test
895drm_hdmi_connector_get_output_format_name_valid_tests[] = {
896 OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_RGB, "RGB"),
897 OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV420, "YUV 4:2:0"),
898 OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV422, "YUV 4:2:2"),
899 OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV444, "YUV 4:4:4"),
900};
901
902static void
903drm_hdmi_connector_get_output_format_name_valid_desc(const struct drm_hdmi_connector_get_output_format_name_test *t,
904 char *desc)
905{
906 sprintf(desc, "%s", t->expected_name);
907}
908
909KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_output_format_name_valid,
910 drm_hdmi_connector_get_output_format_name_valid_tests,
911 drm_hdmi_connector_get_output_format_name_valid_desc);
912
913static void drm_test_drm_hdmi_connector_get_output_format_name_invalid(struct kunit *test)
914{
915 KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_output_format_name(4));
916};
917
918static struct kunit_case drm_hdmi_connector_get_output_format_name_tests[] = {
919 KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_output_format_name,
920 drm_hdmi_connector_get_output_format_name_valid_gen_params),
921 KUNIT_CASE(drm_test_drm_hdmi_connector_get_output_format_name_invalid),
922 { }
923};
924
925static struct kunit_suite drm_hdmi_connector_get_output_format_name_test_suite = {
926 .name = "drm_hdmi_connector_get_output_format_name",
927 .test_cases = drm_hdmi_connector_get_output_format_name_tests,
928};
929
930static void drm_test_drm_connector_attach_broadcast_rgb_property(struct kunit *test)
931{
932 struct drm_connector_init_priv *priv = test->priv;
933 struct drm_connector *connector = &priv->connector;
934 struct drm_property *prop;
935 int ret;
936
937 ret = drmm_connector_init(&priv->drm, connector,
938 &dummy_funcs,
939 DRM_MODE_CONNECTOR_HDMIA,
940 &priv->ddc);
941 KUNIT_ASSERT_EQ(test, ret, 0);
942
943 ret = drm_connector_attach_broadcast_rgb_property(connector);
944 KUNIT_ASSERT_EQ(test, ret, 0);
945
946 prop = connector->broadcast_rgb_property;
947 KUNIT_ASSERT_NOT_NULL(test, prop);
948 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
949}
950
951static void drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(struct kunit *test)
952{
953 struct drm_connector_init_priv *priv = test->priv;
954 struct drm_connector *connector = &priv->connector;
955 struct drm_property *prop;
956 int ret;
957
958 ret = drmm_connector_hdmi_init(&priv->drm, connector,
959 "Vendor", "Product",
960 &dummy_funcs,
961 &dummy_hdmi_funcs,
962 DRM_MODE_CONNECTOR_HDMIA,
963 &priv->ddc,
964 BIT(HDMI_COLORSPACE_RGB),
965 8);
966 KUNIT_EXPECT_EQ(test, ret, 0);
967
968 ret = drm_connector_attach_broadcast_rgb_property(connector);
969 KUNIT_ASSERT_EQ(test, ret, 0);
970
971 prop = connector->broadcast_rgb_property;
972 KUNIT_ASSERT_NOT_NULL(test, prop);
973 KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
974}
975
976static struct kunit_case drm_connector_attach_broadcast_rgb_property_tests[] = {
977 KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property),
978 KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector),
979 { }
980};
981
982static struct kunit_suite drm_connector_attach_broadcast_rgb_property_test_suite = {
983 .name = "drm_connector_attach_broadcast_rgb_property",
984 .init = drm_test_connector_init,
985 .test_cases = drm_connector_attach_broadcast_rgb_property_tests,
986};
987
988/*
989 * Test that for a given mode, with 8bpc and an RGB output the TMDS
990 * character rate is equal to the mode pixel clock.
991 */
992static void drm_test_drm_hdmi_compute_mode_clock_rgb(struct kunit *test)
993{
994 struct drm_connector_init_priv *priv = test->priv;
995 const struct drm_display_mode *mode;
996 unsigned long long rate;
997 struct drm_device *drm = &priv->drm;
998
999 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1000 KUNIT_ASSERT_NOT_NULL(test, mode);
1001
1002 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1003
1004 rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
1005 KUNIT_ASSERT_GT(test, rate, 0);
1006 KUNIT_EXPECT_EQ(test, mode->clock * 1000ULL, rate);
1007}
1008
1009/*
1010 * Test that for a given mode, with 10bpc and an RGB output the TMDS
1011 * character rate is equal to 1.25 times the mode pixel clock.
1012 */
1013static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc(struct kunit *test)
1014{
1015 struct drm_connector_init_priv *priv = test->priv;
1016 const struct drm_display_mode *mode;
1017 unsigned long long rate;
1018 struct drm_device *drm = &priv->drm;
1019
1020 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1021 KUNIT_ASSERT_NOT_NULL(test, mode);
1022
1023 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1024
1025 rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
1026 KUNIT_ASSERT_GT(test, rate, 0);
1027 KUNIT_EXPECT_EQ(test, mode->clock * 1250, rate);
1028}
1029
1030/*
1031 * Test that for the VIC-1 mode, with 10bpc and an RGB output the TMDS
1032 * character rate computation fails.
1033 */
1034static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1(struct kunit *test)
1035{
1036 struct drm_connector_init_priv *priv = test->priv;
1037 const struct drm_display_mode *mode;
1038 unsigned long long rate;
1039 struct drm_device *drm = &priv->drm;
1040
1041 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
1042 KUNIT_ASSERT_NOT_NULL(test, mode);
1043
1044 rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
1045 KUNIT_EXPECT_EQ(test, rate, 0);
1046}
1047
1048/*
1049 * Test that for a given mode, with 12bpc and an RGB output the TMDS
1050 * character rate is equal to 1.5 times the mode pixel clock.
1051 */
1052static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc(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, 12, HDMI_COLORSPACE_RGB);
1065 KUNIT_ASSERT_GT(test, rate, 0);
1066 KUNIT_EXPECT_EQ(test, mode->clock * 1500, rate);
1067}
1068
1069/*
1070 * Test that for the VIC-1 mode, with 12bpc and an RGB output the TMDS
1071 * character rate computation fails.
1072 */
1073static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1(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, 1);
1081 KUNIT_ASSERT_NOT_NULL(test, mode);
1082
1083 rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
1084 KUNIT_EXPECT_EQ(test, rate, 0);
1085}
1086
1087/*
1088 * Test that for a mode with the pixel repetition flag, the TMDS
1089 * character rate is indeed double the mode pixel clock.
1090 */
1091static void drm_test_drm_hdmi_compute_mode_clock_rgb_double(struct kunit *test)
1092{
1093 struct drm_connector_init_priv *priv = test->priv;
1094 const struct drm_display_mode *mode;
1095 unsigned long long rate;
1096 struct drm_device *drm = &priv->drm;
1097
1098 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 6);
1099 KUNIT_ASSERT_NOT_NULL(test, mode);
1100
1101 KUNIT_ASSERT_TRUE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1102
1103 rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
1104 KUNIT_ASSERT_GT(test, rate, 0);
1105 KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) * 2, rate);
1106}
1107
1108/*
1109 * Test that the TMDS character rate computation for the VIC modes
1110 * explicitly listed in the spec as supporting YUV420 succeed and return
1111 * half the mode pixel clock.
1112 */
1113static void drm_test_connector_hdmi_compute_mode_clock_yuv420_valid(struct kunit *test)
1114{
1115 struct drm_connector_init_priv *priv = test->priv;
1116 const struct drm_display_mode *mode;
1117 struct drm_device *drm = &priv->drm;
1118 unsigned long long rate;
1119 unsigned int vic = *(unsigned int *)test->param_value;
1120
1121 mode = drm_kunit_display_mode_from_cea_vic(test, drm, vic);
1122 KUNIT_ASSERT_NOT_NULL(test, mode);
1123
1124 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1125
1126 rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV420);
1127 KUNIT_ASSERT_GT(test, rate, 0);
1128 KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) / 2, rate);
1129}
1130
1131static const unsigned int drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[] = {
1132 96, 97, 101, 102, 106, 107,
1133};
1134
1135static void drm_hdmi_compute_mode_clock_yuv420_vic_desc(const unsigned int *vic, char *desc)
1136{
1137 sprintf(desc, "VIC %u", *vic);
1138}
1139
1140KUNIT_ARRAY_PARAM(drm_hdmi_compute_mode_clock_yuv420_valid,
1141 drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests,
1142 drm_hdmi_compute_mode_clock_yuv420_vic_desc);
1143
1144/*
1145 * Test that for a given mode listed supporting it and an YUV420 output
1146 * with 10bpc, the TMDS character rate is equal to 0.625 times the mode
1147 * pixel clock.
1148 */
1149static void drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc(struct kunit *test)
1150{
1151 struct drm_connector_init_priv *priv = test->priv;
1152 const struct drm_display_mode *mode;
1153 struct drm_device *drm = &priv->drm;
1154 unsigned int vic =
1155 drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0];
1156 unsigned long long rate;
1157
1158 mode = drm_kunit_display_mode_from_cea_vic(test, drm, vic);
1159 KUNIT_ASSERT_NOT_NULL(test, mode);
1160
1161 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1162
1163 rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV420);
1164 KUNIT_ASSERT_GT(test, rate, 0);
1165
1166 KUNIT_EXPECT_EQ(test, mode->clock * 625, rate);
1167}
1168
1169/*
1170 * Test that for a given mode listed supporting it and an YUV420 output
1171 * with 12bpc, the TMDS character rate is equal to 0.75 times the mode
1172 * pixel clock.
1173 */
1174static void drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc(struct kunit *test)
1175{
1176 struct drm_connector_init_priv *priv = test->priv;
1177 const struct drm_display_mode *mode;
1178 struct drm_device *drm = &priv->drm;
1179 unsigned int vic =
1180 drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0];
1181 unsigned long long rate;
1182
1183 mode = drm_kunit_display_mode_from_cea_vic(test, drm, vic);
1184 KUNIT_ASSERT_NOT_NULL(test, mode);
1185
1186 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1187
1188 rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV420);
1189 KUNIT_ASSERT_GT(test, rate, 0);
1190
1191 KUNIT_EXPECT_EQ(test, mode->clock * 750, rate);
1192}
1193
1194/*
1195 * Test that for a given mode, the computation of the TMDS character
1196 * rate with 8bpc and a YUV422 output succeeds and returns a rate equal
1197 * to the mode pixel clock.
1198 */
1199static void drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc(struct kunit *test)
1200{
1201 struct drm_connector_init_priv *priv = test->priv;
1202 const struct drm_display_mode *mode;
1203 struct drm_device *drm = &priv->drm;
1204 unsigned long long rate;
1205
1206 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1207 KUNIT_ASSERT_NOT_NULL(test, mode);
1208
1209 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1210
1211 rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV422);
1212 KUNIT_ASSERT_GT(test, rate, 0);
1213 KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1214}
1215
1216/*
1217 * Test that for a given mode, the computation of the TMDS character
1218 * rate with 10bpc and a YUV422 output succeeds and returns a rate equal
1219 * to the mode pixel clock.
1220 */
1221static void drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc(struct kunit *test)
1222{
1223 struct drm_connector_init_priv *priv = test->priv;
1224 const struct drm_display_mode *mode;
1225 struct drm_device *drm = &priv->drm;
1226 unsigned long long rate;
1227
1228 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1229 KUNIT_ASSERT_NOT_NULL(test, mode);
1230
1231 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1232
1233 rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV422);
1234 KUNIT_ASSERT_GT(test, rate, 0);
1235 KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1236}
1237
1238/*
1239 * Test that for a given mode, the computation of the TMDS character
1240 * rate with 12bpc and a YUV422 output succeeds and returns a rate equal
1241 * to the mode pixel clock.
1242 */
1243static void drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc(struct kunit *test)
1244{
1245 struct drm_connector_init_priv *priv = test->priv;
1246 const struct drm_display_mode *mode;
1247 struct drm_device *drm = &priv->drm;
1248 unsigned long long rate;
1249
1250 mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1251 KUNIT_ASSERT_NOT_NULL(test, mode);
1252
1253 KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1254
1255 rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV422);
1256 KUNIT_ASSERT_GT(test, rate, 0);
1257 KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1258}
1259
1260static struct kunit_case drm_hdmi_compute_mode_clock_tests[] = {
1261 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb),
1262 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc),
1263 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1),
1264 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc),
1265 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1),
1266 KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_double),
1267 KUNIT_CASE_PARAM(drm_test_connector_hdmi_compute_mode_clock_yuv420_valid,
1268 drm_hdmi_compute_mode_clock_yuv420_valid_gen_params),
1269 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc),
1270 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc),
1271 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc),
1272 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc),
1273 KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc),
1274 { }
1275};
1276
1277static struct kunit_suite drm_hdmi_compute_mode_clock_test_suite = {
1278 .name = "drm_test_connector_hdmi_compute_mode_clock",
1279 .init = drm_test_connector_init,
1280 .test_cases = drm_hdmi_compute_mode_clock_tests,
1281};
1282
1283kunit_test_suites(
1284 &drmm_connector_hdmi_init_test_suite,
1285 &drmm_connector_init_test_suite,
1286 &drm_connector_attach_broadcast_rgb_property_test_suite,
1287 &drm_get_tv_mode_from_name_test_suite,
1288 &drm_hdmi_compute_mode_clock_test_suite,
1289 &drm_hdmi_connector_get_broadcast_rgb_name_test_suite,
1290 &drm_hdmi_connector_get_output_format_name_test_suite
1291);
1292
1293MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
1294MODULE_DESCRIPTION("Kunit test for drm_modes functions");
1295MODULE_LICENSE("GPL");