xref: /linux/drivers/gpu/drm/tests/drm_connector_test.c (revision 4fa04f4cccc4d81fd6272ca94b879b4d7630ed53)
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 
36 static int dummy_ddc_xfer(struct i2c_adapter *adapter,
37 			  struct i2c_msg *msgs, int num)
38 {
39 	return num;
40 }
41 
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 
52 static void i2c_del_adapter_wrapper(void *ptr)
53 {
54 	struct i2c_adapter *adap = ptr;
55 
56 	i2c_del_adapter(adap);
57 }
58 
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  */
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  */
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  */
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 
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 
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  */
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 
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 };
781 
782 static void
783 drm_get_tv_mode_from_name_valid_desc(const struct drm_get_tv_mode_from_name_test *t,
784 				     char *desc)
785 {
786 	sprintf(desc, "%s", t->name);
787 }
788 
789 KUNIT_ARRAY_PARAM(drm_get_tv_mode_from_name_valid,
790 		  drm_get_tv_mode_from_name_valid_tests,
791 		  drm_get_tv_mode_from_name_valid_desc);
792 
793 static void drm_test_get_tv_mode_from_name_truncated(struct kunit *test)
794 {
795 	const char *name = "NTS";
796 	int ret;
797 
798 	ret = drm_get_tv_mode_from_name(name, strlen(name));
799 	KUNIT_EXPECT_LT(test, ret, 0);
800 };
801 
802 static struct kunit_case drm_get_tv_mode_from_name_tests[] = {
803 	KUNIT_CASE_PARAM(drm_test_get_tv_mode_from_name_valid,
804 			 drm_get_tv_mode_from_name_valid_gen_params),
805 	KUNIT_CASE(drm_test_get_tv_mode_from_name_truncated),
806 	{ }
807 };
808 
809 static struct kunit_suite drm_get_tv_mode_from_name_test_suite = {
810 	.name = "drm_get_tv_mode_from_name",
811 	.test_cases = drm_get_tv_mode_from_name_tests,
812 };
813 
814 struct drm_hdmi_connector_get_broadcast_rgb_name_test {
815 	unsigned int kind;
816 	const char *expected_name;
817 };
818 
819 #define BROADCAST_RGB_TEST(_kind, _name)	\
820 	{					\
821 		.kind = _kind,			\
822 		.expected_name = _name,		\
823 	}
824 
825 static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name(struct kunit *test)
826 {
827 	const struct drm_hdmi_connector_get_broadcast_rgb_name_test *params =
828 		test->param_value;
829 
830 	KUNIT_EXPECT_STREQ(test,
831 			   drm_hdmi_connector_get_broadcast_rgb_name(params->kind),
832 			   params->expected_name);
833 }
834 
835 static const
836 struct drm_hdmi_connector_get_broadcast_rgb_name_test
837 drm_hdmi_connector_get_broadcast_rgb_name_valid_tests[] = {
838 	BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic"),
839 	BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_FULL, "Full"),
840 	BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235"),
841 };
842 
843 static void
844 drm_hdmi_connector_get_broadcast_rgb_name_valid_desc(const struct drm_hdmi_connector_get_broadcast_rgb_name_test *t,
845 						     char *desc)
846 {
847 	sprintf(desc, "%s", t->expected_name);
848 }
849 
850 KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_broadcast_rgb_name_valid,
851 		  drm_hdmi_connector_get_broadcast_rgb_name_valid_tests,
852 		  drm_hdmi_connector_get_broadcast_rgb_name_valid_desc);
853 
854 static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid(struct kunit *test)
855 {
856 	KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_broadcast_rgb_name(3));
857 };
858 
859 static struct kunit_case drm_hdmi_connector_get_broadcast_rgb_name_tests[] = {
860 	KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_broadcast_rgb_name,
861 			 drm_hdmi_connector_get_broadcast_rgb_name_valid_gen_params),
862 	KUNIT_CASE(drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid),
863 	{ }
864 };
865 
866 static struct kunit_suite drm_hdmi_connector_get_broadcast_rgb_name_test_suite = {
867 	.name = "drm_hdmi_connector_get_broadcast_rgb_name",
868 	.test_cases = drm_hdmi_connector_get_broadcast_rgb_name_tests,
869 };
870 
871 struct drm_hdmi_connector_get_output_format_name_test {
872 	unsigned int kind;
873 	const char *expected_name;
874 };
875 
876 #define OUTPUT_FORMAT_TEST(_kind, _name)	\
877 	{					\
878 		.kind = _kind,			\
879 		.expected_name = _name,		\
880 	}
881 
882 static void drm_test_drm_hdmi_connector_get_output_format_name(struct kunit *test)
883 {
884 	const struct drm_hdmi_connector_get_output_format_name_test *params =
885 		test->param_value;
886 
887 	KUNIT_EXPECT_STREQ(test,
888 			   drm_hdmi_connector_get_output_format_name(params->kind),
889 			   params->expected_name);
890 }
891 
892 static const
893 struct drm_hdmi_connector_get_output_format_name_test
894 drm_hdmi_connector_get_output_format_name_valid_tests[] = {
895 	OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_RGB, "RGB"),
896 	OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV420, "YUV 4:2:0"),
897 	OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV422, "YUV 4:2:2"),
898 	OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV444, "YUV 4:4:4"),
899 };
900 
901 static void
902 drm_hdmi_connector_get_output_format_name_valid_desc(const struct drm_hdmi_connector_get_output_format_name_test *t,
903 						     char *desc)
904 {
905 	sprintf(desc, "%s", t->expected_name);
906 }
907 
908 KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_output_format_name_valid,
909 		  drm_hdmi_connector_get_output_format_name_valid_tests,
910 		  drm_hdmi_connector_get_output_format_name_valid_desc);
911 
912 static void drm_test_drm_hdmi_connector_get_output_format_name_invalid(struct kunit *test)
913 {
914 	KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_output_format_name(4));
915 };
916 
917 static struct kunit_case drm_hdmi_connector_get_output_format_name_tests[] = {
918 	KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_output_format_name,
919 			 drm_hdmi_connector_get_output_format_name_valid_gen_params),
920 	KUNIT_CASE(drm_test_drm_hdmi_connector_get_output_format_name_invalid),
921 	{ }
922 };
923 
924 static struct kunit_suite drm_hdmi_connector_get_output_format_name_test_suite = {
925 	.name = "drm_hdmi_connector_get_output_format_name",
926 	.test_cases = drm_hdmi_connector_get_output_format_name_tests,
927 };
928 
929 static void drm_test_drm_connector_attach_broadcast_rgb_property(struct kunit *test)
930 {
931 	struct drm_connector_init_priv *priv = test->priv;
932 	struct drm_connector *connector = &priv->connector;
933 	struct drm_property *prop;
934 	int ret;
935 
936 	ret = drmm_connector_init(&priv->drm, connector,
937 				  &dummy_funcs,
938 				  DRM_MODE_CONNECTOR_HDMIA,
939 				  &priv->ddc);
940 	KUNIT_ASSERT_EQ(test, ret, 0);
941 
942 	ret = drm_connector_attach_broadcast_rgb_property(connector);
943 	KUNIT_ASSERT_EQ(test, ret, 0);
944 
945 	prop = connector->broadcast_rgb_property;
946 	KUNIT_ASSERT_NOT_NULL(test, prop);
947 	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
948 }
949 
950 static void drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(struct kunit *test)
951 {
952 	struct drm_connector_init_priv *priv = test->priv;
953 	struct drm_connector *connector = &priv->connector;
954 	struct drm_property *prop;
955 	int ret;
956 
957 	ret = drmm_connector_hdmi_init(&priv->drm, connector,
958 				       "Vendor", "Product",
959 				       &dummy_funcs,
960 				       &dummy_hdmi_funcs,
961 				       DRM_MODE_CONNECTOR_HDMIA,
962 				       &priv->ddc,
963 				       BIT(HDMI_COLORSPACE_RGB),
964 				       8);
965 	KUNIT_EXPECT_EQ(test, ret, 0);
966 
967 	ret = drm_connector_attach_broadcast_rgb_property(connector);
968 	KUNIT_ASSERT_EQ(test, ret, 0);
969 
970 	prop = connector->broadcast_rgb_property;
971 	KUNIT_ASSERT_NOT_NULL(test, prop);
972 	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
973 }
974 
975 static struct kunit_case drm_connector_attach_broadcast_rgb_property_tests[] = {
976 	KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property),
977 	KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector),
978 	{ }
979 };
980 
981 static struct kunit_suite drm_connector_attach_broadcast_rgb_property_test_suite = {
982 	.name = "drm_connector_attach_broadcast_rgb_property",
983 	.init = drm_test_connector_init,
984 	.test_cases = drm_connector_attach_broadcast_rgb_property_tests,
985 };
986 
987 /*
988  * Test that for a given mode, with 8bpc and an RGB output the TMDS
989  * character rate is equal to the mode pixel clock.
990  */
991 static void drm_test_drm_hdmi_compute_mode_clock_rgb(struct kunit *test)
992 {
993 	struct drm_connector_init_priv *priv = test->priv;
994 	const struct drm_display_mode *mode;
995 	unsigned long long rate;
996 	struct drm_device *drm = &priv->drm;
997 
998 	mode = drm_display_mode_from_cea_vic(drm, 16);
999 	KUNIT_ASSERT_NOT_NULL(test, mode);
1000 
1001 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1002 
1003 	rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
1004 	KUNIT_ASSERT_GT(test, rate, 0);
1005 	KUNIT_EXPECT_EQ(test, mode->clock * 1000ULL, rate);
1006 }
1007 
1008 /*
1009  * Test that for a given mode, with 10bpc and an RGB output the TMDS
1010  * character rate is equal to 1.25 times the mode pixel clock.
1011  */
1012 static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc(struct kunit *test)
1013 {
1014 	struct drm_connector_init_priv *priv = test->priv;
1015 	const struct drm_display_mode *mode;
1016 	unsigned long long rate;
1017 	struct drm_device *drm = &priv->drm;
1018 
1019 	mode = drm_display_mode_from_cea_vic(drm, 16);
1020 	KUNIT_ASSERT_NOT_NULL(test, mode);
1021 
1022 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1023 
1024 	rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
1025 	KUNIT_ASSERT_GT(test, rate, 0);
1026 	KUNIT_EXPECT_EQ(test, mode->clock * 1250, rate);
1027 }
1028 
1029 /*
1030  * Test that for the VIC-1 mode, with 10bpc and an RGB output the TMDS
1031  * character rate computation fails.
1032  */
1033 static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1(struct kunit *test)
1034 {
1035 	struct drm_connector_init_priv *priv = test->priv;
1036 	const struct drm_display_mode *mode;
1037 	unsigned long long rate;
1038 	struct drm_device *drm = &priv->drm;
1039 
1040 	mode = drm_display_mode_from_cea_vic(drm, 1);
1041 	KUNIT_ASSERT_NOT_NULL(test, mode);
1042 
1043 	rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
1044 	KUNIT_EXPECT_EQ(test, rate, 0);
1045 }
1046 
1047 /*
1048  * Test that for a given mode, with 12bpc and an RGB output the TMDS
1049  * character rate is equal to 1.5 times the mode pixel clock.
1050  */
1051 static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc(struct kunit *test)
1052 {
1053 	struct drm_connector_init_priv *priv = test->priv;
1054 	const struct drm_display_mode *mode;
1055 	unsigned long long rate;
1056 	struct drm_device *drm = &priv->drm;
1057 
1058 	mode = drm_display_mode_from_cea_vic(drm, 16);
1059 	KUNIT_ASSERT_NOT_NULL(test, mode);
1060 
1061 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1062 
1063 	rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
1064 	KUNIT_ASSERT_GT(test, rate, 0);
1065 	KUNIT_EXPECT_EQ(test, mode->clock * 1500, rate);
1066 }
1067 
1068 /*
1069  * Test that for the VIC-1 mode, with 12bpc and an RGB output the TMDS
1070  * character rate computation fails.
1071  */
1072 static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1(struct kunit *test)
1073 {
1074 	struct drm_connector_init_priv *priv = test->priv;
1075 	const struct drm_display_mode *mode;
1076 	unsigned long long rate;
1077 	struct drm_device *drm = &priv->drm;
1078 
1079 	mode = drm_display_mode_from_cea_vic(drm, 1);
1080 	KUNIT_ASSERT_NOT_NULL(test, mode);
1081 
1082 	rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
1083 	KUNIT_EXPECT_EQ(test, rate, 0);
1084 }
1085 
1086 /*
1087  * Test that for a mode with the pixel repetition flag, the TMDS
1088  * character rate is indeed double the mode pixel clock.
1089  */
1090 static void drm_test_drm_hdmi_compute_mode_clock_rgb_double(struct kunit *test)
1091 {
1092 	struct drm_connector_init_priv *priv = test->priv;
1093 	const struct drm_display_mode *mode;
1094 	unsigned long long rate;
1095 	struct drm_device *drm = &priv->drm;
1096 
1097 	mode = drm_display_mode_from_cea_vic(drm, 6);
1098 	KUNIT_ASSERT_NOT_NULL(test, mode);
1099 
1100 	KUNIT_ASSERT_TRUE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1101 
1102 	rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
1103 	KUNIT_ASSERT_GT(test, rate, 0);
1104 	KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) * 2, rate);
1105 }
1106 
1107 /*
1108  * Test that the TMDS character rate computation for the VIC modes
1109  * explicitly listed in the spec as supporting YUV420 succeed and return
1110  * half the mode pixel clock.
1111  */
1112 static void drm_test_connector_hdmi_compute_mode_clock_yuv420_valid(struct kunit *test)
1113 {
1114 	struct drm_connector_init_priv *priv = test->priv;
1115 	const struct drm_display_mode *mode;
1116 	struct drm_device *drm = &priv->drm;
1117 	unsigned long long rate;
1118 	unsigned int vic = *(unsigned int *)test->param_value;
1119 
1120 	mode = drm_display_mode_from_cea_vic(drm, vic);
1121 	KUNIT_ASSERT_NOT_NULL(test, mode);
1122 
1123 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1124 
1125 	rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV420);
1126 	KUNIT_ASSERT_GT(test, rate, 0);
1127 	KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) / 2, rate);
1128 }
1129 
1130 static const unsigned int drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[] = {
1131 	96, 97, 101, 102, 106, 107,
1132 };
1133 
1134 static void drm_hdmi_compute_mode_clock_yuv420_vic_desc(const unsigned int *vic, char *desc)
1135 {
1136 	sprintf(desc, "VIC %u", *vic);
1137 }
1138 
1139 KUNIT_ARRAY_PARAM(drm_hdmi_compute_mode_clock_yuv420_valid,
1140 		  drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests,
1141 		  drm_hdmi_compute_mode_clock_yuv420_vic_desc);
1142 
1143 /*
1144  * Test that for a given mode listed supporting it and an YUV420 output
1145  * with 10bpc, the TMDS character rate is equal to 0.625 times the mode
1146  * pixel clock.
1147  */
1148 static void drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc(struct kunit *test)
1149 {
1150 	struct drm_connector_init_priv *priv = test->priv;
1151 	const struct drm_display_mode *mode;
1152 	struct drm_device *drm = &priv->drm;
1153 	unsigned int vic =
1154 		drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0];
1155 	unsigned long long rate;
1156 
1157 	mode = drm_display_mode_from_cea_vic(drm, vic);
1158 	KUNIT_ASSERT_NOT_NULL(test, mode);
1159 
1160 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1161 
1162 	rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV420);
1163 	KUNIT_ASSERT_GT(test, rate, 0);
1164 
1165 	KUNIT_EXPECT_EQ(test, mode->clock * 625, rate);
1166 }
1167 
1168 /*
1169  * Test that for a given mode listed supporting it and an YUV420 output
1170  * with 12bpc, the TMDS character rate is equal to 0.75 times the mode
1171  * pixel clock.
1172  */
1173 static void drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc(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 int vic =
1179 		drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0];
1180 	unsigned long long rate;
1181 
1182 	mode = drm_display_mode_from_cea_vic(drm, vic);
1183 	KUNIT_ASSERT_NOT_NULL(test, mode);
1184 
1185 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1186 
1187 	rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV420);
1188 	KUNIT_ASSERT_GT(test, rate, 0);
1189 
1190 	KUNIT_EXPECT_EQ(test, mode->clock * 750, rate);
1191 }
1192 
1193 /*
1194  * Test that for a given mode, the computation of the TMDS character
1195  * rate with 8bpc and a YUV422 output succeeds and returns a rate equal
1196  * to the mode pixel clock.
1197  */
1198 static void drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc(struct kunit *test)
1199 {
1200 	struct drm_connector_init_priv *priv = test->priv;
1201 	const struct drm_display_mode *mode;
1202 	struct drm_device *drm = &priv->drm;
1203 	unsigned long long rate;
1204 
1205 	mode = drm_display_mode_from_cea_vic(drm, 16);
1206 	KUNIT_ASSERT_NOT_NULL(test, mode);
1207 
1208 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1209 
1210 	rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV422);
1211 	KUNIT_ASSERT_GT(test, rate, 0);
1212 	KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1213 }
1214 
1215 /*
1216  * Test that for a given mode, the computation of the TMDS character
1217  * rate with 10bpc and a YUV422 output succeeds and returns a rate equal
1218  * to the mode pixel clock.
1219  */
1220 static void drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc(struct kunit *test)
1221 {
1222 	struct drm_connector_init_priv *priv = test->priv;
1223 	const struct drm_display_mode *mode;
1224 	struct drm_device *drm = &priv->drm;
1225 	unsigned long long rate;
1226 
1227 	mode = drm_display_mode_from_cea_vic(drm, 16);
1228 	KUNIT_ASSERT_NOT_NULL(test, mode);
1229 
1230 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1231 
1232 	rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV422);
1233 	KUNIT_ASSERT_GT(test, rate, 0);
1234 	KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1235 }
1236 
1237 /*
1238  * Test that for a given mode, the computation of the TMDS character
1239  * rate with 12bpc and a YUV422 output succeeds and returns a rate equal
1240  * to the mode pixel clock.
1241  */
1242 static void drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc(struct kunit *test)
1243 {
1244 	struct drm_connector_init_priv *priv = test->priv;
1245 	const struct drm_display_mode *mode;
1246 	struct drm_device *drm = &priv->drm;
1247 	unsigned long long rate;
1248 
1249 	mode = drm_display_mode_from_cea_vic(drm, 16);
1250 	KUNIT_ASSERT_NOT_NULL(test, mode);
1251 
1252 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1253 
1254 	rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV422);
1255 	KUNIT_ASSERT_GT(test, rate, 0);
1256 	KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1257 }
1258 
1259 static struct kunit_case drm_hdmi_compute_mode_clock_tests[] = {
1260 	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb),
1261 	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc),
1262 	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1),
1263 	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc),
1264 	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1),
1265 	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_double),
1266 	KUNIT_CASE_PARAM(drm_test_connector_hdmi_compute_mode_clock_yuv420_valid,
1267 			 drm_hdmi_compute_mode_clock_yuv420_valid_gen_params),
1268 	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc),
1269 	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc),
1270 	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc),
1271 	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc),
1272 	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc),
1273 	{ }
1274 };
1275 
1276 static struct kunit_suite drm_hdmi_compute_mode_clock_test_suite = {
1277 	.name = "drm_test_connector_hdmi_compute_mode_clock",
1278 	.init = drm_test_connector_init,
1279 	.test_cases = drm_hdmi_compute_mode_clock_tests,
1280 };
1281 
1282 kunit_test_suites(
1283 	&drmm_connector_hdmi_init_test_suite,
1284 	&drmm_connector_init_test_suite,
1285 	&drm_connector_attach_broadcast_rgb_property_test_suite,
1286 	&drm_get_tv_mode_from_name_test_suite,
1287 	&drm_hdmi_compute_mode_clock_test_suite,
1288 	&drm_hdmi_connector_get_broadcast_rgb_name_test_suite,
1289 	&drm_hdmi_connector_get_output_format_name_test_suite
1290 );
1291 
1292 MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
1293 MODULE_LICENSE("GPL");
1294