xref: /linux/drivers/gpu/drm/tests/drm_connector_test.c (revision 269ce3bd62e8ad83dadc80a2f755a799697ca4a3)
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