xref: /linux/drivers/gpu/drm/tests/drm_connector_test.c (revision f378b77227bc4732922c57f92be89438bb1018a1)
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 a connector with an invalid maximum bpc
226  * count fails.
227  */
228 static void drm_test_connector_hdmi_init_bpc_invalid(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 				       "Vendor", "Product",
235 				       &dummy_funcs,
236 				       &dummy_hdmi_funcs,
237 				       DRM_MODE_CONNECTOR_HDMIA,
238 				       &priv->ddc,
239 				       BIT(HDMI_COLORSPACE_RGB),
240 				       9);
241 	KUNIT_EXPECT_LT(test, ret, 0);
242 }
243 
244 /*
245  * Test that the registration of a connector with a null maximum bpc
246  * count fails.
247  */
248 static void drm_test_connector_hdmi_init_bpc_null(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", "Product",
255 				       &dummy_funcs,
256 				       &dummy_hdmi_funcs,
257 				       DRM_MODE_CONNECTOR_HDMIA,
258 				       &priv->ddc,
259 				       BIT(HDMI_COLORSPACE_RGB),
260 				       0);
261 	KUNIT_EXPECT_LT(test, ret, 0);
262 }
263 
264 /*
265  * Test that the registration of a connector with a maximum bpc count of
266  * 8 succeeds, registers the max bpc property, but doesn't register the
267  * HDR output metadata one.
268  */
269 static void drm_test_connector_hdmi_init_bpc_8(struct kunit *test)
270 {
271 	struct drm_connector_init_priv *priv = test->priv;
272 	struct drm_connector_state *state;
273 	struct drm_connector *connector = &priv->connector;
274 	struct drm_property *prop;
275 	uint64_t val;
276 	int ret;
277 
278 	ret = drmm_connector_hdmi_init(&priv->drm, connector,
279 				       "Vendor", "Product",
280 				       &dummy_funcs,
281 				       &dummy_hdmi_funcs,
282 				       DRM_MODE_CONNECTOR_HDMIA,
283 				       &priv->ddc,
284 				       BIT(HDMI_COLORSPACE_RGB),
285 				       8);
286 	KUNIT_EXPECT_EQ(test, ret, 0);
287 
288 	prop = connector->max_bpc_property;
289 	KUNIT_ASSERT_NOT_NULL(test, prop);
290 	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
291 
292 	ret = drm_object_property_get_default_value(&connector->base, prop, &val);
293 	KUNIT_EXPECT_EQ(test, ret, 0);
294 	KUNIT_EXPECT_EQ(test, val, 8);
295 
296 	state = connector->state;
297 	KUNIT_EXPECT_EQ(test, state->max_bpc, 8);
298 	KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 8);
299 
300 	prop = priv->drm.mode_config.hdr_output_metadata_property;
301 	KUNIT_ASSERT_NOT_NULL(test, prop);
302 	KUNIT_EXPECT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
303 }
304 
305 /*
306  * Test that the registration of a connector with a maximum bpc count of
307  * 10 succeeds and registers the max bpc and HDR output metadata
308  * properties.
309  */
310 static void drm_test_connector_hdmi_init_bpc_10(struct kunit *test)
311 {
312 	struct drm_connector_init_priv *priv = test->priv;
313 	struct drm_connector_state *state;
314 	struct drm_connector *connector = &priv->connector;
315 	struct drm_property *prop;
316 	uint64_t val;
317 	int ret;
318 
319 	ret = drmm_connector_hdmi_init(&priv->drm, connector,
320 				       "Vendor", "Product",
321 				       &dummy_funcs,
322 				       &dummy_hdmi_funcs,
323 				       DRM_MODE_CONNECTOR_HDMIA,
324 				       &priv->ddc,
325 				       BIT(HDMI_COLORSPACE_RGB),
326 				       10);
327 	KUNIT_EXPECT_EQ(test, ret, 0);
328 
329 	prop = connector->max_bpc_property;
330 	KUNIT_ASSERT_NOT_NULL(test, prop);
331 	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
332 
333 	ret = drm_object_property_get_default_value(&connector->base, prop, &val);
334 	KUNIT_EXPECT_EQ(test, ret, 0);
335 	KUNIT_EXPECT_EQ(test, val, 10);
336 
337 	state = connector->state;
338 	KUNIT_EXPECT_EQ(test, state->max_bpc, 10);
339 	KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 10);
340 
341 	prop = priv->drm.mode_config.hdr_output_metadata_property;
342 	KUNIT_ASSERT_NOT_NULL(test, prop);
343 	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
344 }
345 
346 /*
347  * Test that the registration of a connector with a maximum bpc count of
348  * 12 succeeds and registers the max bpc and HDR output metadata
349  * properties.
350  */
351 static void drm_test_connector_hdmi_init_bpc_12(struct kunit *test)
352 {
353 	struct drm_connector_init_priv *priv = test->priv;
354 	struct drm_connector_state *state;
355 	struct drm_connector *connector = &priv->connector;
356 	struct drm_property *prop;
357 	uint64_t val;
358 	int ret;
359 
360 	ret = drmm_connector_hdmi_init(&priv->drm, connector,
361 				       "Vendor", "Product",
362 				       &dummy_funcs,
363 				       &dummy_hdmi_funcs,
364 				       DRM_MODE_CONNECTOR_HDMIA,
365 				       &priv->ddc,
366 				       BIT(HDMI_COLORSPACE_RGB),
367 				       12);
368 	KUNIT_EXPECT_EQ(test, ret, 0);
369 
370 	prop = connector->max_bpc_property;
371 	KUNIT_ASSERT_NOT_NULL(test, prop);
372 	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
373 
374 	ret = drm_object_property_get_default_value(&connector->base, prop, &val);
375 	KUNIT_EXPECT_EQ(test, ret, 0);
376 	KUNIT_EXPECT_EQ(test, val, 12);
377 
378 	state = connector->state;
379 	KUNIT_EXPECT_EQ(test, state->max_bpc, 12);
380 	KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 12);
381 
382 	prop = priv->drm.mode_config.hdr_output_metadata_property;
383 	KUNIT_ASSERT_NOT_NULL(test, prop);
384 	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
385 }
386 
387 /*
388  * Test that the registration of an HDMI connector with no supported
389  * format fails.
390  */
391 static void drm_test_connector_hdmi_init_formats_empty(struct kunit *test)
392 {
393 	struct drm_connector_init_priv *priv = test->priv;
394 	int ret;
395 
396 	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
397 				       "Vendor", "Product",
398 				       &dummy_funcs,
399 				       &dummy_hdmi_funcs,
400 				       DRM_MODE_CONNECTOR_HDMIA,
401 				       &priv->ddc,
402 				       0,
403 				       8);
404 	KUNIT_EXPECT_LT(test, ret, 0);
405 }
406 
407 /*
408  * Test that the registration of an HDMI connector not listing RGB as a
409  * supported format fails.
410  */
411 static void drm_test_connector_hdmi_init_formats_no_rgb(struct kunit *test)
412 {
413 	struct drm_connector_init_priv *priv = test->priv;
414 	int ret;
415 
416 	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
417 				       "Vendor", "Product",
418 				       &dummy_funcs,
419 				       &dummy_hdmi_funcs,
420 				       DRM_MODE_CONNECTOR_HDMIA,
421 				       &priv->ddc,
422 				       BIT(HDMI_COLORSPACE_YUV422),
423 				       8);
424 	KUNIT_EXPECT_LT(test, ret, 0);
425 }
426 
427 /*
428  * Test that the registration of an HDMI connector with an HDMI
429  * connector type succeeds.
430  */
431 static void drm_test_connector_hdmi_init_type_valid(struct kunit *test)
432 {
433 	struct drm_connector_init_priv *priv = test->priv;
434 	unsigned int connector_type = *(unsigned int *)test->param_value;
435 	int ret;
436 
437 	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
438 				       "Vendor", "Product",
439 				       &dummy_funcs,
440 				       &dummy_hdmi_funcs,
441 				       connector_type,
442 				       &priv->ddc,
443 				       BIT(HDMI_COLORSPACE_RGB),
444 				       8);
445 	KUNIT_EXPECT_EQ(test, ret, 0);
446 }
447 
448 static const unsigned int drm_connector_hdmi_init_type_valid_tests[] = {
449 	DRM_MODE_CONNECTOR_HDMIA,
450 	DRM_MODE_CONNECTOR_HDMIB,
451 };
452 
453 static void drm_connector_hdmi_init_type_desc(const unsigned int *type, char *desc)
454 {
455 	sprintf(desc, "%s", drm_get_connector_type_name(*type));
456 }
457 
458 KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_valid,
459 		  drm_connector_hdmi_init_type_valid_tests,
460 		  drm_connector_hdmi_init_type_desc);
461 
462 /*
463  * Test that the registration of an HDMI connector with an !HDMI
464  * connector type fails.
465  */
466 static void drm_test_connector_hdmi_init_type_invalid(struct kunit *test)
467 {
468 	struct drm_connector_init_priv *priv = test->priv;
469 	unsigned int connector_type = *(unsigned int *)test->param_value;
470 	int ret;
471 
472 	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
473 				       "Vendor", "Product",
474 				       &dummy_funcs,
475 				       &dummy_hdmi_funcs,
476 				       connector_type,
477 				       &priv->ddc,
478 				       BIT(HDMI_COLORSPACE_RGB),
479 				       8);
480 	KUNIT_EXPECT_LT(test, ret, 0);
481 }
482 
483 static const unsigned int drm_connector_hdmi_init_type_invalid_tests[] = {
484 	DRM_MODE_CONNECTOR_Unknown,
485 	DRM_MODE_CONNECTOR_VGA,
486 	DRM_MODE_CONNECTOR_DVII,
487 	DRM_MODE_CONNECTOR_DVID,
488 	DRM_MODE_CONNECTOR_DVIA,
489 	DRM_MODE_CONNECTOR_Composite,
490 	DRM_MODE_CONNECTOR_SVIDEO,
491 	DRM_MODE_CONNECTOR_LVDS,
492 	DRM_MODE_CONNECTOR_Component,
493 	DRM_MODE_CONNECTOR_9PinDIN,
494 	DRM_MODE_CONNECTOR_DisplayPort,
495 	DRM_MODE_CONNECTOR_TV,
496 	DRM_MODE_CONNECTOR_eDP,
497 	DRM_MODE_CONNECTOR_VIRTUAL,
498 	DRM_MODE_CONNECTOR_DSI,
499 	DRM_MODE_CONNECTOR_DPI,
500 	DRM_MODE_CONNECTOR_WRITEBACK,
501 	DRM_MODE_CONNECTOR_SPI,
502 	DRM_MODE_CONNECTOR_USB,
503 };
504 
505 KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_invalid,
506 		  drm_connector_hdmi_init_type_invalid_tests,
507 		  drm_connector_hdmi_init_type_desc);
508 
509 static struct kunit_case drmm_connector_hdmi_init_tests[] = {
510 	KUNIT_CASE(drm_test_connector_hdmi_init_valid),
511 	KUNIT_CASE(drm_test_connector_hdmi_init_bpc_8),
512 	KUNIT_CASE(drm_test_connector_hdmi_init_bpc_10),
513 	KUNIT_CASE(drm_test_connector_hdmi_init_bpc_12),
514 	KUNIT_CASE(drm_test_connector_hdmi_init_bpc_invalid),
515 	KUNIT_CASE(drm_test_connector_hdmi_init_bpc_null),
516 	KUNIT_CASE(drm_test_connector_hdmi_init_formats_empty),
517 	KUNIT_CASE(drm_test_connector_hdmi_init_formats_no_rgb),
518 	KUNIT_CASE(drm_test_connector_hdmi_init_null_ddc),
519 	KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_valid,
520 			 drm_connector_hdmi_init_type_valid_gen_params),
521 	KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_invalid,
522 			 drm_connector_hdmi_init_type_invalid_gen_params),
523 	{ }
524 };
525 
526 static struct kunit_suite drmm_connector_hdmi_init_test_suite = {
527 	.name = "drmm_connector_hdmi_init",
528 	.init = drm_test_connector_init,
529 	.test_cases = drmm_connector_hdmi_init_tests,
530 };
531 
532 struct drm_get_tv_mode_from_name_test {
533 	const char *name;
534 	enum drm_connector_tv_mode expected_mode;
535 };
536 
537 #define TV_MODE_NAME(_name, _mode)		\
538 	{					\
539 		.name = _name,			\
540 		.expected_mode = _mode,		\
541 	}
542 
543 static void drm_test_get_tv_mode_from_name_valid(struct kunit *test)
544 {
545 	const struct drm_get_tv_mode_from_name_test *params = test->param_value;
546 
547 	KUNIT_EXPECT_EQ(test,
548 			drm_get_tv_mode_from_name(params->name, strlen(params->name)),
549 			params->expected_mode);
550 }
551 
552 static const
553 struct drm_get_tv_mode_from_name_test drm_get_tv_mode_from_name_valid_tests[] = {
554 	TV_MODE_NAME("NTSC", DRM_MODE_TV_MODE_NTSC),
555 	TV_MODE_NAME("NTSC-443", DRM_MODE_TV_MODE_NTSC_443),
556 	TV_MODE_NAME("NTSC-J", DRM_MODE_TV_MODE_NTSC_J),
557 	TV_MODE_NAME("PAL", DRM_MODE_TV_MODE_PAL),
558 	TV_MODE_NAME("PAL-M", DRM_MODE_TV_MODE_PAL_M),
559 	TV_MODE_NAME("PAL-N", DRM_MODE_TV_MODE_PAL_N),
560 	TV_MODE_NAME("SECAM", DRM_MODE_TV_MODE_SECAM),
561 };
562 
563 static void
564 drm_get_tv_mode_from_name_valid_desc(const struct drm_get_tv_mode_from_name_test *t,
565 				     char *desc)
566 {
567 	sprintf(desc, "%s", t->name);
568 }
569 
570 KUNIT_ARRAY_PARAM(drm_get_tv_mode_from_name_valid,
571 		  drm_get_tv_mode_from_name_valid_tests,
572 		  drm_get_tv_mode_from_name_valid_desc);
573 
574 static void drm_test_get_tv_mode_from_name_truncated(struct kunit *test)
575 {
576 	const char *name = "NTS";
577 	int ret;
578 
579 	ret = drm_get_tv_mode_from_name(name, strlen(name));
580 	KUNIT_EXPECT_LT(test, ret, 0);
581 };
582 
583 static struct kunit_case drm_get_tv_mode_from_name_tests[] = {
584 	KUNIT_CASE_PARAM(drm_test_get_tv_mode_from_name_valid,
585 			 drm_get_tv_mode_from_name_valid_gen_params),
586 	KUNIT_CASE(drm_test_get_tv_mode_from_name_truncated),
587 	{ }
588 };
589 
590 static struct kunit_suite drm_get_tv_mode_from_name_test_suite = {
591 	.name = "drm_get_tv_mode_from_name",
592 	.test_cases = drm_get_tv_mode_from_name_tests,
593 };
594 
595 struct drm_hdmi_connector_get_broadcast_rgb_name_test {
596 	unsigned int kind;
597 	const char *expected_name;
598 };
599 
600 #define BROADCAST_RGB_TEST(_kind, _name)	\
601 	{					\
602 		.kind = _kind,			\
603 		.expected_name = _name,		\
604 	}
605 
606 static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name(struct kunit *test)
607 {
608 	const struct drm_hdmi_connector_get_broadcast_rgb_name_test *params =
609 		test->param_value;
610 
611 	KUNIT_EXPECT_STREQ(test,
612 			   drm_hdmi_connector_get_broadcast_rgb_name(params->kind),
613 			   params->expected_name);
614 }
615 
616 static const
617 struct drm_hdmi_connector_get_broadcast_rgb_name_test
618 drm_hdmi_connector_get_broadcast_rgb_name_valid_tests[] = {
619 	BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic"),
620 	BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_FULL, "Full"),
621 	BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235"),
622 };
623 
624 static void
625 drm_hdmi_connector_get_broadcast_rgb_name_valid_desc(const struct drm_hdmi_connector_get_broadcast_rgb_name_test *t,
626 						     char *desc)
627 {
628 	sprintf(desc, "%s", t->expected_name);
629 }
630 
631 KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_broadcast_rgb_name_valid,
632 		  drm_hdmi_connector_get_broadcast_rgb_name_valid_tests,
633 		  drm_hdmi_connector_get_broadcast_rgb_name_valid_desc);
634 
635 static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid(struct kunit *test)
636 {
637 	KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_broadcast_rgb_name(3));
638 };
639 
640 static struct kunit_case drm_hdmi_connector_get_broadcast_rgb_name_tests[] = {
641 	KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_broadcast_rgb_name,
642 			 drm_hdmi_connector_get_broadcast_rgb_name_valid_gen_params),
643 	KUNIT_CASE(drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid),
644 	{ }
645 };
646 
647 static struct kunit_suite drm_hdmi_connector_get_broadcast_rgb_name_test_suite = {
648 	.name = "drm_hdmi_connector_get_broadcast_rgb_name",
649 	.test_cases = drm_hdmi_connector_get_broadcast_rgb_name_tests,
650 };
651 
652 struct drm_hdmi_connector_get_output_format_name_test {
653 	unsigned int kind;
654 	const char *expected_name;
655 };
656 
657 #define OUTPUT_FORMAT_TEST(_kind, _name)	\
658 	{					\
659 		.kind = _kind,			\
660 		.expected_name = _name,		\
661 	}
662 
663 static void drm_test_drm_hdmi_connector_get_output_format_name(struct kunit *test)
664 {
665 	const struct drm_hdmi_connector_get_output_format_name_test *params =
666 		test->param_value;
667 
668 	KUNIT_EXPECT_STREQ(test,
669 			   drm_hdmi_connector_get_output_format_name(params->kind),
670 			   params->expected_name);
671 }
672 
673 static const
674 struct drm_hdmi_connector_get_output_format_name_test
675 drm_hdmi_connector_get_output_format_name_valid_tests[] = {
676 	OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_RGB, "RGB"),
677 	OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV420, "YUV 4:2:0"),
678 	OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV422, "YUV 4:2:2"),
679 	OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV444, "YUV 4:4:4"),
680 };
681 
682 static void
683 drm_hdmi_connector_get_output_format_name_valid_desc(const struct drm_hdmi_connector_get_output_format_name_test *t,
684 						     char *desc)
685 {
686 	sprintf(desc, "%s", t->expected_name);
687 }
688 
689 KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_output_format_name_valid,
690 		  drm_hdmi_connector_get_output_format_name_valid_tests,
691 		  drm_hdmi_connector_get_output_format_name_valid_desc);
692 
693 static void drm_test_drm_hdmi_connector_get_output_format_name_invalid(struct kunit *test)
694 {
695 	KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_output_format_name(4));
696 };
697 
698 static struct kunit_case drm_hdmi_connector_get_output_format_name_tests[] = {
699 	KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_output_format_name,
700 			 drm_hdmi_connector_get_output_format_name_valid_gen_params),
701 	KUNIT_CASE(drm_test_drm_hdmi_connector_get_output_format_name_invalid),
702 	{ }
703 };
704 
705 static struct kunit_suite drm_hdmi_connector_get_output_format_name_test_suite = {
706 	.name = "drm_hdmi_connector_get_output_format_name",
707 	.test_cases = drm_hdmi_connector_get_output_format_name_tests,
708 };
709 
710 static void drm_test_drm_connector_attach_broadcast_rgb_property(struct kunit *test)
711 {
712 	struct drm_connector_init_priv *priv = test->priv;
713 	struct drm_connector *connector = &priv->connector;
714 	struct drm_property *prop;
715 	int ret;
716 
717 	ret = drmm_connector_init(&priv->drm, connector,
718 				  &dummy_funcs,
719 				  DRM_MODE_CONNECTOR_HDMIA,
720 				  &priv->ddc);
721 	KUNIT_ASSERT_EQ(test, ret, 0);
722 
723 	ret = drm_connector_attach_broadcast_rgb_property(connector);
724 	KUNIT_ASSERT_EQ(test, ret, 0);
725 
726 	prop = connector->broadcast_rgb_property;
727 	KUNIT_ASSERT_NOT_NULL(test, prop);
728 	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
729 }
730 
731 static void drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(struct kunit *test)
732 {
733 	struct drm_connector_init_priv *priv = test->priv;
734 	struct drm_connector *connector = &priv->connector;
735 	struct drm_property *prop;
736 	int ret;
737 
738 	ret = drmm_connector_hdmi_init(&priv->drm, connector,
739 				       "Vendor", "Product",
740 				       &dummy_funcs,
741 				       &dummy_hdmi_funcs,
742 				       DRM_MODE_CONNECTOR_HDMIA,
743 				       &priv->ddc,
744 				       BIT(HDMI_COLORSPACE_RGB),
745 				       8);
746 	KUNIT_EXPECT_EQ(test, ret, 0);
747 
748 	ret = drm_connector_attach_broadcast_rgb_property(connector);
749 	KUNIT_ASSERT_EQ(test, ret, 0);
750 
751 	prop = connector->broadcast_rgb_property;
752 	KUNIT_ASSERT_NOT_NULL(test, prop);
753 	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
754 }
755 
756 static struct kunit_case drm_connector_attach_broadcast_rgb_property_tests[] = {
757 	KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property),
758 	KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector),
759 	{ }
760 };
761 
762 static struct kunit_suite drm_connector_attach_broadcast_rgb_property_test_suite = {
763 	.name = "drm_connector_attach_broadcast_rgb_property",
764 	.init = drm_test_connector_init,
765 	.test_cases = drm_connector_attach_broadcast_rgb_property_tests,
766 };
767 
768 /*
769  * Test that for a given mode, with 8bpc and an RGB output the TMDS
770  * character rate is equal to the mode pixel clock.
771  */
772 static void drm_test_drm_hdmi_compute_mode_clock_rgb(struct kunit *test)
773 {
774 	struct drm_connector_init_priv *priv = test->priv;
775 	const struct drm_display_mode *mode;
776 	unsigned long long rate;
777 	struct drm_device *drm = &priv->drm;
778 
779 	mode = drm_display_mode_from_cea_vic(drm, 16);
780 	KUNIT_ASSERT_NOT_NULL(test, mode);
781 
782 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
783 
784 	rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
785 	KUNIT_ASSERT_GT(test, rate, 0);
786 	KUNIT_EXPECT_EQ(test, mode->clock * 1000ULL, rate);
787 }
788 
789 /*
790  * Test that for a given mode, with 10bpc and an RGB output the TMDS
791  * character rate is equal to 1.25 times the mode pixel clock.
792  */
793 static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc(struct kunit *test)
794 {
795 	struct drm_connector_init_priv *priv = test->priv;
796 	const struct drm_display_mode *mode;
797 	unsigned long long rate;
798 	struct drm_device *drm = &priv->drm;
799 
800 	mode = drm_display_mode_from_cea_vic(drm, 16);
801 	KUNIT_ASSERT_NOT_NULL(test, mode);
802 
803 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
804 
805 	rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
806 	KUNIT_ASSERT_GT(test, rate, 0);
807 	KUNIT_EXPECT_EQ(test, mode->clock * 1250, rate);
808 }
809 
810 /*
811  * Test that for the VIC-1 mode, with 10bpc and an RGB output the TMDS
812  * character rate computation fails.
813  */
814 static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1(struct kunit *test)
815 {
816 	struct drm_connector_init_priv *priv = test->priv;
817 	const struct drm_display_mode *mode;
818 	unsigned long long rate;
819 	struct drm_device *drm = &priv->drm;
820 
821 	mode = drm_display_mode_from_cea_vic(drm, 1);
822 	KUNIT_ASSERT_NOT_NULL(test, mode);
823 
824 	rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
825 	KUNIT_EXPECT_EQ(test, rate, 0);
826 }
827 
828 /*
829  * Test that for a given mode, with 12bpc and an RGB output the TMDS
830  * character rate is equal to 1.5 times the mode pixel clock.
831  */
832 static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc(struct kunit *test)
833 {
834 	struct drm_connector_init_priv *priv = test->priv;
835 	const struct drm_display_mode *mode;
836 	unsigned long long rate;
837 	struct drm_device *drm = &priv->drm;
838 
839 	mode = drm_display_mode_from_cea_vic(drm, 16);
840 	KUNIT_ASSERT_NOT_NULL(test, mode);
841 
842 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
843 
844 	rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
845 	KUNIT_ASSERT_GT(test, rate, 0);
846 	KUNIT_EXPECT_EQ(test, mode->clock * 1500, rate);
847 }
848 
849 /*
850  * Test that for the VIC-1 mode, with 12bpc and an RGB output the TMDS
851  * character rate computation fails.
852  */
853 static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1(struct kunit *test)
854 {
855 	struct drm_connector_init_priv *priv = test->priv;
856 	const struct drm_display_mode *mode;
857 	unsigned long long rate;
858 	struct drm_device *drm = &priv->drm;
859 
860 	mode = drm_display_mode_from_cea_vic(drm, 1);
861 	KUNIT_ASSERT_NOT_NULL(test, mode);
862 
863 	rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
864 	KUNIT_EXPECT_EQ(test, rate, 0);
865 }
866 
867 /*
868  * Test that for a mode with the pixel repetition flag, the TMDS
869  * character rate is indeed double the mode pixel clock.
870  */
871 static void drm_test_drm_hdmi_compute_mode_clock_rgb_double(struct kunit *test)
872 {
873 	struct drm_connector_init_priv *priv = test->priv;
874 	const struct drm_display_mode *mode;
875 	unsigned long long rate;
876 	struct drm_device *drm = &priv->drm;
877 
878 	mode = drm_display_mode_from_cea_vic(drm, 6);
879 	KUNIT_ASSERT_NOT_NULL(test, mode);
880 
881 	KUNIT_ASSERT_TRUE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
882 
883 	rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
884 	KUNIT_ASSERT_GT(test, rate, 0);
885 	KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) * 2, rate);
886 }
887 
888 /*
889  * Test that the TMDS character rate computation for the VIC modes
890  * explicitly listed in the spec as supporting YUV420 succeed and return
891  * half the mode pixel clock.
892  */
893 static void drm_test_connector_hdmi_compute_mode_clock_yuv420_valid(struct kunit *test)
894 {
895 	struct drm_connector_init_priv *priv = test->priv;
896 	const struct drm_display_mode *mode;
897 	struct drm_device *drm = &priv->drm;
898 	unsigned long long rate;
899 	unsigned int vic = *(unsigned int *)test->param_value;
900 
901 	mode = drm_display_mode_from_cea_vic(drm, vic);
902 	KUNIT_ASSERT_NOT_NULL(test, mode);
903 
904 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
905 
906 	rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV420);
907 	KUNIT_ASSERT_GT(test, rate, 0);
908 	KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) / 2, rate);
909 }
910 
911 static const unsigned int drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[] = {
912 	96, 97, 101, 102, 106, 107,
913 };
914 
915 static void drm_hdmi_compute_mode_clock_yuv420_vic_desc(const unsigned int *vic, char *desc)
916 {
917 	sprintf(desc, "VIC %u", *vic);
918 }
919 
920 KUNIT_ARRAY_PARAM(drm_hdmi_compute_mode_clock_yuv420_valid,
921 		  drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests,
922 		  drm_hdmi_compute_mode_clock_yuv420_vic_desc);
923 
924 /*
925  * Test that for a given mode listed supporting it and an YUV420 output
926  * with 10bpc, the TMDS character rate is equal to 0.625 times the mode
927  * pixel clock.
928  */
929 static void drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc(struct kunit *test)
930 {
931 	struct drm_connector_init_priv *priv = test->priv;
932 	const struct drm_display_mode *mode;
933 	struct drm_device *drm = &priv->drm;
934 	unsigned int vic =
935 		drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0];
936 	unsigned long long rate;
937 
938 	mode = drm_display_mode_from_cea_vic(drm, vic);
939 	KUNIT_ASSERT_NOT_NULL(test, mode);
940 
941 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
942 
943 	rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV420);
944 	KUNIT_ASSERT_GT(test, rate, 0);
945 
946 	KUNIT_EXPECT_EQ(test, mode->clock * 625, rate);
947 }
948 
949 /*
950  * Test that for a given mode listed supporting it and an YUV420 output
951  * with 12bpc, the TMDS character rate is equal to 0.75 times the mode
952  * pixel clock.
953  */
954 static void drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc(struct kunit *test)
955 {
956 	struct drm_connector_init_priv *priv = test->priv;
957 	const struct drm_display_mode *mode;
958 	struct drm_device *drm = &priv->drm;
959 	unsigned int vic =
960 		drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0];
961 	unsigned long long rate;
962 
963 	mode = drm_display_mode_from_cea_vic(drm, vic);
964 	KUNIT_ASSERT_NOT_NULL(test, mode);
965 
966 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
967 
968 	rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV420);
969 	KUNIT_ASSERT_GT(test, rate, 0);
970 
971 	KUNIT_EXPECT_EQ(test, mode->clock * 750, rate);
972 }
973 
974 /*
975  * Test that for a given mode, the computation of the TMDS character
976  * rate with 8bpc and a YUV422 output succeeds and returns a rate equal
977  * to the mode pixel clock.
978  */
979 static void drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc(struct kunit *test)
980 {
981 	struct drm_connector_init_priv *priv = test->priv;
982 	const struct drm_display_mode *mode;
983 	struct drm_device *drm = &priv->drm;
984 	unsigned long long rate;
985 
986 	mode = drm_display_mode_from_cea_vic(drm, 16);
987 	KUNIT_ASSERT_NOT_NULL(test, mode);
988 
989 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
990 
991 	rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV422);
992 	KUNIT_ASSERT_GT(test, rate, 0);
993 	KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
994 }
995 
996 /*
997  * Test that for a given mode, the computation of the TMDS character
998  * rate with 10bpc and a YUV422 output succeeds and returns a rate equal
999  * to the mode pixel clock.
1000  */
1001 static void drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc(struct kunit *test)
1002 {
1003 	struct drm_connector_init_priv *priv = test->priv;
1004 	const struct drm_display_mode *mode;
1005 	struct drm_device *drm = &priv->drm;
1006 	unsigned long long rate;
1007 
1008 	mode = drm_display_mode_from_cea_vic(drm, 16);
1009 	KUNIT_ASSERT_NOT_NULL(test, mode);
1010 
1011 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1012 
1013 	rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV422);
1014 	KUNIT_ASSERT_GT(test, rate, 0);
1015 	KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1016 }
1017 
1018 /*
1019  * Test that for a given mode, the computation of the TMDS character
1020  * rate with 12bpc and a YUV422 output succeeds and returns a rate equal
1021  * to the mode pixel clock.
1022  */
1023 static void drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc(struct kunit *test)
1024 {
1025 	struct drm_connector_init_priv *priv = test->priv;
1026 	const struct drm_display_mode *mode;
1027 	struct drm_device *drm = &priv->drm;
1028 	unsigned long long rate;
1029 
1030 	mode = drm_display_mode_from_cea_vic(drm, 16);
1031 	KUNIT_ASSERT_NOT_NULL(test, mode);
1032 
1033 	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1034 
1035 	rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV422);
1036 	KUNIT_ASSERT_GT(test, rate, 0);
1037 	KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1038 }
1039 
1040 static struct kunit_case drm_hdmi_compute_mode_clock_tests[] = {
1041 	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb),
1042 	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc),
1043 	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1),
1044 	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc),
1045 	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1),
1046 	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_double),
1047 	KUNIT_CASE_PARAM(drm_test_connector_hdmi_compute_mode_clock_yuv420_valid,
1048 			 drm_hdmi_compute_mode_clock_yuv420_valid_gen_params),
1049 	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc),
1050 	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc),
1051 	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc),
1052 	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc),
1053 	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc),
1054 	{ }
1055 };
1056 
1057 static struct kunit_suite drm_hdmi_compute_mode_clock_test_suite = {
1058 	.name = "drm_test_connector_hdmi_compute_mode_clock",
1059 	.init = drm_test_connector_init,
1060 	.test_cases = drm_hdmi_compute_mode_clock_tests,
1061 };
1062 
1063 kunit_test_suites(
1064 	&drmm_connector_hdmi_init_test_suite,
1065 	&drmm_connector_init_test_suite,
1066 	&drm_connector_attach_broadcast_rgb_property_test_suite,
1067 	&drm_get_tv_mode_from_name_test_suite,
1068 	&drm_hdmi_compute_mode_clock_test_suite,
1069 	&drm_hdmi_connector_get_broadcast_rgb_name_test_suite,
1070 	&drm_hdmi_connector_get_output_format_name_test_suite
1071 );
1072 
1073 MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
1074 MODULE_LICENSE("GPL");
1075