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
21 struct drm_connector_init_priv {
22 struct drm_device drm;
23 struct drm_connector connector;
24 struct i2c_adapter ddc;
25 };
26
27 static const struct drm_connector_hdmi_funcs dummy_hdmi_funcs = {
28 };
29
30 static 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
dummy_ddc_xfer(struct i2c_adapter * adapter,struct i2c_msg * msgs,int num)36 static int dummy_ddc_xfer(struct i2c_adapter *adapter,
37 struct i2c_msg *msgs, int num)
38 {
39 return num;
40 }
41
dummy_ddc_func(struct i2c_adapter * adapter)42 static u32 dummy_ddc_func(struct i2c_adapter *adapter)
43 {
44 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
45 }
46
47 static const struct i2c_algorithm dummy_ddc_algorithm = {
48 .master_xfer = dummy_ddc_xfer,
49 .functionality = dummy_ddc_func,
50 };
51
i2c_del_adapter_wrapper(void * ptr)52 static void i2c_del_adapter_wrapper(void *ptr)
53 {
54 struct i2c_adapter *adap = ptr;
55
56 i2c_del_adapter(adap);
57 }
58
drm_test_connector_init(struct kunit * test)59 static 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 */
drm_test_drmm_connector_init(struct kunit * test)92 static 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 */
drm_test_drmm_connector_init_null_ddc(struct kunit * test)108 static 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 */
drm_test_drmm_connector_init_type_valid(struct kunit * test)124 static 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
137 static 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
drm_connector_init_type_desc(const unsigned int * type,char * desc)161 static 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
166 KUNIT_ARRAY_PARAM(drm_connector_init_type_valid,
167 drm_connector_init_type_valid_tests,
168 drm_connector_init_type_desc);
169
170 static 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
178 static 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 */
drm_test_connector_hdmi_init_valid(struct kunit * test)188 static 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 */
drm_test_connector_hdmi_init_null_ddc(struct kunit * test)208 static 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 */
drm_test_connector_hdmi_init_null_vendor(struct kunit * test)228 static 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 */
drm_test_connector_hdmi_init_null_product(struct kunit * test)248 static 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 */
drm_test_connector_hdmi_init_product_valid(struct kunit * test)268 static 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 */
drm_test_connector_hdmi_init_product_length_exact(struct kunit * test)299 static 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 */
drm_test_connector_hdmi_init_product_length_too_long(struct kunit * test)331 static 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 */
drm_test_connector_hdmi_init_vendor_valid(struct kunit * test)354 static 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 */
drm_test_connector_hdmi_init_vendor_length_exact(struct kunit * test)385 static 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 */
drm_test_connector_hdmi_init_vendor_length_too_long(struct kunit * test)416 static 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 */
drm_test_connector_hdmi_init_bpc_invalid(struct kunit * test)439 static 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 */
drm_test_connector_hdmi_init_bpc_null(struct kunit * test)459 static 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 */
drm_test_connector_hdmi_init_bpc_8(struct kunit * test)480 static 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 */
drm_test_connector_hdmi_init_bpc_10(struct kunit * test)521 static 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 */
drm_test_connector_hdmi_init_bpc_12(struct kunit * test)562 static 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 */
drm_test_connector_hdmi_init_formats_empty(struct kunit * test)602 static 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 */
drm_test_connector_hdmi_init_formats_no_rgb(struct kunit * test)622 static 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 */
drm_test_connector_hdmi_init_type_valid(struct kunit * test)642 static 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
659 static const unsigned int drm_connector_hdmi_init_type_valid_tests[] = {
660 DRM_MODE_CONNECTOR_HDMIA,
661 DRM_MODE_CONNECTOR_HDMIB,
662 };
663
drm_connector_hdmi_init_type_desc(const unsigned int * type,char * desc)664 static 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
669 KUNIT_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 */
drm_test_connector_hdmi_init_type_invalid(struct kunit * test)677 static 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
694 static 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
716 KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_invalid,
717 drm_connector_hdmi_init_type_invalid_tests,
718 drm_connector_hdmi_init_type_desc);
719
720 static 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
745 static 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
751 struct 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
drm_test_get_tv_mode_from_name_valid(struct kunit * test)762 static 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
771 static const
772 struct 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
783 static void
drm_get_tv_mode_from_name_valid_desc(const struct drm_get_tv_mode_from_name_test * t,char * desc)784 drm_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
790 KUNIT_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
drm_test_get_tv_mode_from_name_truncated(struct kunit * test)794 static 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
803 static 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
810 static 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
815 struct 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
drm_test_drm_hdmi_connector_get_broadcast_rgb_name(struct kunit * test)826 static 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
836 static const
837 struct drm_hdmi_connector_get_broadcast_rgb_name_test
838 drm_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
844 static void
drm_hdmi_connector_get_broadcast_rgb_name_valid_desc(const struct drm_hdmi_connector_get_broadcast_rgb_name_test * t,char * desc)845 drm_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
851 KUNIT_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
drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid(struct kunit * test)855 static 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
860 static 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
867 static 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
872 struct 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
drm_test_drm_hdmi_connector_get_output_format_name(struct kunit * test)883 static 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
893 static const
894 struct drm_hdmi_connector_get_output_format_name_test
895 drm_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
902 static void
drm_hdmi_connector_get_output_format_name_valid_desc(const struct drm_hdmi_connector_get_output_format_name_test * t,char * desc)903 drm_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
909 KUNIT_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
drm_test_drm_hdmi_connector_get_output_format_name_invalid(struct kunit * test)913 static 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
918 static 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
925 static 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
drm_test_drm_connector_attach_broadcast_rgb_property(struct kunit * test)930 static 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
drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(struct kunit * test)951 static 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
976 static 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
982 static 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 */
drm_test_drm_hdmi_compute_mode_clock_rgb(struct kunit * test)992 static 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 */
drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc(struct kunit * test)1013 static 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 */
drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1(struct kunit * test)1034 static 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 */
drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc(struct kunit * test)1052 static 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 */
drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1(struct kunit * test)1073 static 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 */
drm_test_drm_hdmi_compute_mode_clock_rgb_double(struct kunit * test)1091 static 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 */
drm_test_connector_hdmi_compute_mode_clock_yuv420_valid(struct kunit * test)1113 static 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
1131 static const unsigned int drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[] = {
1132 96, 97, 101, 102, 106, 107,
1133 };
1134
drm_hdmi_compute_mode_clock_yuv420_vic_desc(const unsigned int * vic,char * desc)1135 static void drm_hdmi_compute_mode_clock_yuv420_vic_desc(const unsigned int *vic, char *desc)
1136 {
1137 sprintf(desc, "VIC %u", *vic);
1138 }
1139
1140 KUNIT_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 */
drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc(struct kunit * test)1149 static 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 */
drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc(struct kunit * test)1174 static 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 */
drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc(struct kunit * test)1199 static 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 */
drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc(struct kunit * test)1221 static 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 */
drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc(struct kunit * test)1243 static 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
1260 static 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
1277 static 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
1283 kunit_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
1293 MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
1294 MODULE_DESCRIPTION("Kunit test for drm_modes functions");
1295 MODULE_LICENSE("GPL");
1296