Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Kunit test for drm_modes functions
   4 */
   5
   6#include <linux/i2c.h>
   7
   8#include <drm/drm_atomic_state_helper.h>
   9#include <drm/drm_connector.h>
  10#include <drm/drm_drv.h>
  11#include <drm/drm_edid.h>
  12#include <drm/drm_kunit_helpers.h>
  13#include <drm/drm_modes.h>
  14
  15#include <drm/display/drm_hdmi_helper.h>
  16
  17#include <kunit/test.h>
  18
  19#include "../drm_crtc_internal.h"
  20
  21struct drm_connector_init_priv {
  22	struct drm_device drm;
  23	struct drm_connector connector;
  24	struct i2c_adapter ddc;
  25};
  26
  27static const struct drm_connector_hdmi_funcs dummy_hdmi_funcs = {
  28};
  29
  30static const struct drm_connector_funcs dummy_funcs = {
  31	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
  32	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
  33	.reset			= drm_atomic_helper_connector_reset,
  34};
  35
  36static int dummy_ddc_xfer(struct i2c_adapter *adapter,
  37			  struct i2c_msg *msgs, int num)
  38{
  39	return num;
  40}
  41
  42static u32 dummy_ddc_func(struct i2c_adapter *adapter)
  43{
  44	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
  45}
  46
  47static const struct i2c_algorithm dummy_ddc_algorithm = {
  48	.master_xfer = dummy_ddc_xfer,
  49	.functionality = dummy_ddc_func,
  50};
  51
  52static void i2c_del_adapter_wrapper(void *ptr)
  53{
  54	struct i2c_adapter *adap = ptr;
  55
  56	i2c_del_adapter(adap);
  57}
  58
  59static int drm_test_connector_init(struct kunit *test)
  60{
  61	struct drm_connector_init_priv *priv;
  62	struct device *dev;
  63	int ret;
  64
  65	dev = drm_kunit_helper_alloc_device(test);
  66	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
  67
  68	priv = drm_kunit_helper_alloc_drm_device(test, dev,
  69						 struct drm_connector_init_priv, drm,
  70						 DRIVER_MODESET | DRIVER_ATOMIC);
  71	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
  72
  73	strscpy(priv->ddc.name, "dummy-connector-ddc", sizeof(priv->ddc.name));
  74	priv->ddc.owner = THIS_MODULE;
  75	priv->ddc.algo = &dummy_ddc_algorithm;
  76	priv->ddc.dev.parent = dev;
  77
  78	ret = i2c_add_adapter(&priv->ddc);
  79	KUNIT_ASSERT_EQ(test, ret, 0);
  80
  81	ret = kunit_add_action_or_reset(test, i2c_del_adapter_wrapper, &priv->ddc);
  82	KUNIT_ASSERT_EQ(test, ret, 0);
  83
  84	test->priv = priv;
  85	return 0;
  86}
  87
  88/*
  89 * Test that the registration of a bog standard connector works as
  90 * expected and doesn't report any error.
  91 */
  92static void drm_test_drmm_connector_init(struct kunit *test)
  93{
  94	struct drm_connector_init_priv *priv = test->priv;
  95	int ret;
  96
  97	ret = drmm_connector_init(&priv->drm, &priv->connector,
  98				  &dummy_funcs,
  99				  DRM_MODE_CONNECTOR_HDMIA,
 100				  &priv->ddc);
 101	KUNIT_EXPECT_EQ(test, ret, 0);
 102}
 103
 104/*
 105 * Test that the registration of a connector without a DDC adapter
 106 * doesn't report any error.
 107 */
 108static void drm_test_drmm_connector_init_null_ddc(struct kunit *test)
 109{
 110	struct drm_connector_init_priv *priv = test->priv;
 111	int ret;
 112
 113	ret = drmm_connector_init(&priv->drm, &priv->connector,
 114				  &dummy_funcs,
 115				  DRM_MODE_CONNECTOR_HDMIA,
 116				  NULL);
 117	KUNIT_EXPECT_EQ(test, ret, 0);
 118}
 119
 120/*
 121 * Test that the registration of a connector succeeds for all possible
 122 * connector types.
 123 */
 124static void drm_test_drmm_connector_init_type_valid(struct kunit *test)
 125{
 126	struct drm_connector_init_priv *priv = test->priv;
 127	unsigned int connector_type = *(unsigned int *)test->param_value;
 128	int ret;
 129
 130	ret = drmm_connector_init(&priv->drm, &priv->connector,
 131				  &dummy_funcs,
 132				  connector_type,
 133				  &priv->ddc);
 134	KUNIT_EXPECT_EQ(test, ret, 0);
 135}
 136
 137static const unsigned int drm_connector_init_type_valid_tests[] = {
 138	DRM_MODE_CONNECTOR_Unknown,
 139	DRM_MODE_CONNECTOR_VGA,
 140	DRM_MODE_CONNECTOR_DVII,
 141	DRM_MODE_CONNECTOR_DVID,
 142	DRM_MODE_CONNECTOR_DVIA,
 143	DRM_MODE_CONNECTOR_Composite,
 144	DRM_MODE_CONNECTOR_SVIDEO,
 145	DRM_MODE_CONNECTOR_LVDS,
 146	DRM_MODE_CONNECTOR_Component,
 147	DRM_MODE_CONNECTOR_9PinDIN,
 148	DRM_MODE_CONNECTOR_DisplayPort,
 149	DRM_MODE_CONNECTOR_HDMIA,
 150	DRM_MODE_CONNECTOR_HDMIB,
 151	DRM_MODE_CONNECTOR_TV,
 152	DRM_MODE_CONNECTOR_eDP,
 153	DRM_MODE_CONNECTOR_VIRTUAL,
 154	DRM_MODE_CONNECTOR_DSI,
 155	DRM_MODE_CONNECTOR_DPI,
 156	DRM_MODE_CONNECTOR_WRITEBACK,
 157	DRM_MODE_CONNECTOR_SPI,
 158	DRM_MODE_CONNECTOR_USB,
 159};
 160
 161static void drm_connector_init_type_desc(const unsigned int *type, char *desc)
 162{
 163	sprintf(desc, "%s", drm_get_connector_type_name(*type));
 164}
 165
 166KUNIT_ARRAY_PARAM(drm_connector_init_type_valid,
 167		  drm_connector_init_type_valid_tests,
 168		  drm_connector_init_type_desc);
 169
 170static struct kunit_case drmm_connector_init_tests[] = {
 171	KUNIT_CASE(drm_test_drmm_connector_init),
 172	KUNIT_CASE(drm_test_drmm_connector_init_null_ddc),
 173	KUNIT_CASE_PARAM(drm_test_drmm_connector_init_type_valid,
 174			 drm_connector_init_type_valid_gen_params),
 175	{ }
 176};
 177
 178static struct kunit_suite drmm_connector_init_test_suite = {
 179	.name = "drmm_connector_init",
 180	.init = drm_test_connector_init,
 181	.test_cases = drmm_connector_init_tests,
 182};
 183
 184/*
 185 * Test that the registration of a bog standard connector works as
 186 * expected and doesn't report any error.
 187 */
 188static void drm_test_connector_hdmi_init_valid(struct kunit *test)
 189{
 190	struct drm_connector_init_priv *priv = test->priv;
 191	int ret;
 192
 193	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 194				       "Vendor", "Product",
 195				       &dummy_funcs,
 196				       &dummy_hdmi_funcs,
 197				       DRM_MODE_CONNECTOR_HDMIA,
 198				       &priv->ddc,
 199				       BIT(HDMI_COLORSPACE_RGB),
 200				       8);
 201	KUNIT_EXPECT_EQ(test, ret, 0);
 202}
 203
 204/*
 205 * Test that the registration of a connector without a DDC adapter
 206 * doesn't report any error.
 207 */
 208static void drm_test_connector_hdmi_init_null_ddc(struct kunit *test)
 209{
 210	struct drm_connector_init_priv *priv = test->priv;
 211	int ret;
 212
 213	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 214				       "Vendor", "Product",
 215				       &dummy_funcs,
 216				       &dummy_hdmi_funcs,
 217				       DRM_MODE_CONNECTOR_HDMIA,
 218				       NULL,
 219				       BIT(HDMI_COLORSPACE_RGB),
 220				       8);
 221	KUNIT_EXPECT_EQ(test, ret, 0);
 222}
 223
 224/*
 225 * Test that the registration of an HDMI connector with a NULL vendor
 226 * fails.
 227 */
 228static void drm_test_connector_hdmi_init_null_vendor(struct kunit *test)
 229{
 230	struct drm_connector_init_priv *priv = test->priv;
 231	int ret;
 232
 233	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 234				       NULL, "Product",
 235				       &dummy_funcs,
 236				       &dummy_hdmi_funcs,
 237				       DRM_MODE_CONNECTOR_HDMIA,
 238				       &priv->ddc,
 239				       BIT(HDMI_COLORSPACE_RGB),
 240				       8);
 241	KUNIT_EXPECT_LT(test, ret, 0);
 242}
 243
 244/*
 245 * Test that the registration of an HDMI connector with a NULL product
 246 * fails.
 247 */
 248static void drm_test_connector_hdmi_init_null_product(struct kunit *test)
 249{
 250	struct drm_connector_init_priv *priv = test->priv;
 251	int ret;
 252
 253	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 254				       "Vendor", NULL,
 255				       &dummy_funcs,
 256				       &dummy_hdmi_funcs,
 257				       DRM_MODE_CONNECTOR_HDMIA,
 258				       &priv->ddc,
 259				       BIT(HDMI_COLORSPACE_RGB),
 260				       8);
 261	KUNIT_EXPECT_LT(test, ret, 0);
 262}
 263
 264/*
 265 * Test that the registration of a connector with a valid, shorter than
 266 * the max length, product name succeeds, and is stored padded with 0.
 267 */
 268static void drm_test_connector_hdmi_init_product_valid(struct kunit *test)
 269{
 270	struct drm_connector_init_priv *priv = test->priv;
 271	const unsigned char expected_product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] = {
 272		'P', 'r', 'o', 'd',
 273	};
 274	const char *product_name = "Prod";
 275	int ret;
 276
 277	KUNIT_ASSERT_LT(test, strlen(product_name), DRM_CONNECTOR_HDMI_PRODUCT_LEN);
 278
 279	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 280				       "Vendor", product_name,
 281				       &dummy_funcs,
 282				       &dummy_hdmi_funcs,
 283				       DRM_MODE_CONNECTOR_HDMIA,
 284				       &priv->ddc,
 285				       BIT(HDMI_COLORSPACE_RGB),
 286				       8);
 287	KUNIT_EXPECT_EQ(test, ret, 0);
 288	KUNIT_EXPECT_MEMEQ(test,
 289			   priv->connector.hdmi.product,
 290			   expected_product,
 291			   sizeof(priv->connector.hdmi.product));
 292}
 293
 294/*
 295 * Test that the registration of a connector with a valid, at max
 296 * length, product name succeeds, and is stored padded without any
 297 * trailing \0.
 298 */
 299static void drm_test_connector_hdmi_init_product_length_exact(struct kunit *test)
 300{
 301	struct drm_connector_init_priv *priv = test->priv;
 302	const unsigned char expected_product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] = {
 303		'P', 'r', 'o', 'd', 'u', 'c', 't',
 304		'P', 'r', 'o', 'd', 'u', 'c', 't',
 305		'P', 'r',
 306	};
 307	const char *product_name = "ProductProductPr";
 308	int ret;
 309
 310	KUNIT_ASSERT_EQ(test, strlen(product_name), DRM_CONNECTOR_HDMI_PRODUCT_LEN);
 311
 312	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 313				       "Vendor", product_name,
 314				       &dummy_funcs,
 315				       &dummy_hdmi_funcs,
 316				       DRM_MODE_CONNECTOR_HDMIA,
 317				       &priv->ddc,
 318				       BIT(HDMI_COLORSPACE_RGB),
 319				       8);
 320	KUNIT_EXPECT_EQ(test, ret, 0);
 321	KUNIT_EXPECT_MEMEQ(test,
 322			   priv->connector.hdmi.product,
 323			   expected_product,
 324			   sizeof(priv->connector.hdmi.product));
 325}
 326
 327/*
 328 * Test that the registration of a connector with a product name larger
 329 * than the maximum length fails.
 330 */
 331static void drm_test_connector_hdmi_init_product_length_too_long(struct kunit *test)
 332{
 333	struct drm_connector_init_priv *priv = test->priv;
 334	const char *product_name = "ProductProductProduct";
 335	int ret;
 336
 337	KUNIT_ASSERT_GT(test, strlen(product_name), DRM_CONNECTOR_HDMI_PRODUCT_LEN);
 338
 339	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 340				       "Vendor", product_name,
 341				       &dummy_funcs,
 342				       &dummy_hdmi_funcs,
 343				       DRM_MODE_CONNECTOR_HDMIA,
 344				       &priv->ddc,
 345				       BIT(HDMI_COLORSPACE_RGB),
 346				       8);
 347	KUNIT_EXPECT_LT(test, ret, 0);
 348}
 349
 350/*
 351 * Test that the registration of a connector with a vendor name smaller
 352 * than the maximum length succeeds, and is stored padded with zeros.
 353 */
 354static void drm_test_connector_hdmi_init_vendor_valid(struct kunit *test)
 355{
 356	struct drm_connector_init_priv *priv = test->priv;
 357	const char expected_vendor[DRM_CONNECTOR_HDMI_VENDOR_LEN] = {
 358		'V', 'e', 'n', 'd',
 359	};
 360	const char *vendor_name = "Vend";
 361	int ret;
 362
 363	KUNIT_ASSERT_LT(test, strlen(vendor_name), DRM_CONNECTOR_HDMI_VENDOR_LEN);
 364
 365	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 366				       vendor_name, "Product",
 367				       &dummy_funcs,
 368				       &dummy_hdmi_funcs,
 369				       DRM_MODE_CONNECTOR_HDMIA,
 370				       &priv->ddc,
 371				       BIT(HDMI_COLORSPACE_RGB),
 372				       8);
 373	KUNIT_EXPECT_EQ(test, ret, 0);
 374	KUNIT_EXPECT_MEMEQ(test,
 375			   priv->connector.hdmi.vendor,
 376			   expected_vendor,
 377			   sizeof(priv->connector.hdmi.vendor));
 378}
 379
 380/*
 381 * Test that the registration of a connector with a vendor name at the
 382 * maximum length succeeds, and is stored padded without the trailing
 383 * zero.
 384 */
 385static void drm_test_connector_hdmi_init_vendor_length_exact(struct kunit *test)
 386{
 387	struct drm_connector_init_priv *priv = test->priv;
 388	const char expected_vendor[DRM_CONNECTOR_HDMI_VENDOR_LEN] = {
 389		'V', 'e', 'n', 'd', 'o', 'r',
 390		'V', 'e',
 391	};
 392	const char *vendor_name = "VendorVe";
 393	int ret;
 394
 395	KUNIT_ASSERT_EQ(test, strlen(vendor_name), DRM_CONNECTOR_HDMI_VENDOR_LEN);
 396
 397	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 398				       vendor_name, "Product",
 399				       &dummy_funcs,
 400				       &dummy_hdmi_funcs,
 401				       DRM_MODE_CONNECTOR_HDMIA,
 402				       &priv->ddc,
 403				       BIT(HDMI_COLORSPACE_RGB),
 404				       8);
 405	KUNIT_EXPECT_EQ(test, ret, 0);
 406	KUNIT_EXPECT_MEMEQ(test,
 407			   priv->connector.hdmi.vendor,
 408			   expected_vendor,
 409			   sizeof(priv->connector.hdmi.vendor));
 410}
 411
 412/*
 413 * Test that the registration of a connector with a vendor name larger
 414 * than the maximum length fails.
 415 */
 416static void drm_test_connector_hdmi_init_vendor_length_too_long(struct kunit *test)
 417{
 418	struct drm_connector_init_priv *priv = test->priv;
 419	const char *vendor_name = "VendorVendor";
 420	int ret;
 421
 422	KUNIT_ASSERT_GT(test, strlen(vendor_name), DRM_CONNECTOR_HDMI_VENDOR_LEN);
 423
 424	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 425				       vendor_name, "Product",
 426				       &dummy_funcs,
 427				       &dummy_hdmi_funcs,
 428				       DRM_MODE_CONNECTOR_HDMIA,
 429				       &priv->ddc,
 430				       BIT(HDMI_COLORSPACE_RGB),
 431				       8);
 432	KUNIT_EXPECT_LT(test, ret, 0);
 433}
 434
 435/*
 436 * Test that the registration of a connector with an invalid maximum bpc
 437 * count fails.
 438 */
 439static void drm_test_connector_hdmi_init_bpc_invalid(struct kunit *test)
 440{
 441	struct drm_connector_init_priv *priv = test->priv;
 442	int ret;
 443
 444	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 445				       "Vendor", "Product",
 446				       &dummy_funcs,
 447				       &dummy_hdmi_funcs,
 448				       DRM_MODE_CONNECTOR_HDMIA,
 449				       &priv->ddc,
 450				       BIT(HDMI_COLORSPACE_RGB),
 451				       9);
 452	KUNIT_EXPECT_LT(test, ret, 0);
 453}
 454
 455/*
 456 * Test that the registration of a connector with a null maximum bpc
 457 * count fails.
 458 */
 459static void drm_test_connector_hdmi_init_bpc_null(struct kunit *test)
 460{
 461	struct drm_connector_init_priv *priv = test->priv;
 462	int ret;
 463
 464	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 465				       "Vendor", "Product",
 466				       &dummy_funcs,
 467				       &dummy_hdmi_funcs,
 468				       DRM_MODE_CONNECTOR_HDMIA,
 469				       &priv->ddc,
 470				       BIT(HDMI_COLORSPACE_RGB),
 471				       0);
 472	KUNIT_EXPECT_LT(test, ret, 0);
 473}
 474
 475/*
 476 * Test that the registration of a connector with a maximum bpc count of
 477 * 8 succeeds, registers the max bpc property, but doesn't register the
 478 * HDR output metadata one.
 479 */
 480static void drm_test_connector_hdmi_init_bpc_8(struct kunit *test)
 481{
 482	struct drm_connector_init_priv *priv = test->priv;
 483	struct drm_connector_state *state;
 484	struct drm_connector *connector = &priv->connector;
 485	struct drm_property *prop;
 486	uint64_t val;
 487	int ret;
 488
 489	ret = drmm_connector_hdmi_init(&priv->drm, connector,
 490				       "Vendor", "Product",
 491				       &dummy_funcs,
 492				       &dummy_hdmi_funcs,
 493				       DRM_MODE_CONNECTOR_HDMIA,
 494				       &priv->ddc,
 495				       BIT(HDMI_COLORSPACE_RGB),
 496				       8);
 497	KUNIT_EXPECT_EQ(test, ret, 0);
 498
 499	prop = connector->max_bpc_property;
 500	KUNIT_ASSERT_NOT_NULL(test, prop);
 501	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
 502
 503	ret = drm_object_property_get_default_value(&connector->base, prop, &val);
 504	KUNIT_EXPECT_EQ(test, ret, 0);
 505	KUNIT_EXPECT_EQ(test, val, 8);
 506
 507	state = connector->state;
 508	KUNIT_EXPECT_EQ(test, state->max_bpc, 8);
 509	KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 8);
 510
 511	prop = priv->drm.mode_config.hdr_output_metadata_property;
 512	KUNIT_ASSERT_NOT_NULL(test, prop);
 513	KUNIT_EXPECT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
 514}
 515
 516/*
 517 * Test that the registration of a connector with a maximum bpc count of
 518 * 10 succeeds and registers the max bpc and HDR output metadata
 519 * properties.
 520 */
 521static void drm_test_connector_hdmi_init_bpc_10(struct kunit *test)
 522{
 523	struct drm_connector_init_priv *priv = test->priv;
 524	struct drm_connector_state *state;
 525	struct drm_connector *connector = &priv->connector;
 526	struct drm_property *prop;
 527	uint64_t val;
 528	int ret;
 529
 530	ret = drmm_connector_hdmi_init(&priv->drm, connector,
 531				       "Vendor", "Product",
 532				       &dummy_funcs,
 533				       &dummy_hdmi_funcs,
 534				       DRM_MODE_CONNECTOR_HDMIA,
 535				       &priv->ddc,
 536				       BIT(HDMI_COLORSPACE_RGB),
 537				       10);
 538	KUNIT_EXPECT_EQ(test, ret, 0);
 539
 540	prop = connector->max_bpc_property;
 541	KUNIT_ASSERT_NOT_NULL(test, prop);
 542	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
 543
 544	ret = drm_object_property_get_default_value(&connector->base, prop, &val);
 545	KUNIT_EXPECT_EQ(test, ret, 0);
 546	KUNIT_EXPECT_EQ(test, val, 10);
 547
 548	state = connector->state;
 549	KUNIT_EXPECT_EQ(test, state->max_bpc, 10);
 550	KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 10);
 551
 552	prop = priv->drm.mode_config.hdr_output_metadata_property;
 553	KUNIT_ASSERT_NOT_NULL(test, prop);
 554	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
 555}
 556
 557/*
 558 * Test that the registration of a connector with a maximum bpc count of
 559 * 12 succeeds and registers the max bpc and HDR output metadata
 560 * properties.
 561 */
 562static void drm_test_connector_hdmi_init_bpc_12(struct kunit *test)
 563{
 564	struct drm_connector_init_priv *priv = test->priv;
 565	struct drm_connector_state *state;
 566	struct drm_connector *connector = &priv->connector;
 567	struct drm_property *prop;
 568	uint64_t val;
 569	int ret;
 570
 571	ret = drmm_connector_hdmi_init(&priv->drm, connector,
 572				       "Vendor", "Product",
 573				       &dummy_funcs,
 574				       &dummy_hdmi_funcs,
 575				       DRM_MODE_CONNECTOR_HDMIA,
 576				       &priv->ddc,
 577				       BIT(HDMI_COLORSPACE_RGB),
 578				       12);
 579	KUNIT_EXPECT_EQ(test, ret, 0);
 580
 581	prop = connector->max_bpc_property;
 582	KUNIT_ASSERT_NOT_NULL(test, prop);
 583	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
 584
 585	ret = drm_object_property_get_default_value(&connector->base, prop, &val);
 586	KUNIT_EXPECT_EQ(test, ret, 0);
 587	KUNIT_EXPECT_EQ(test, val, 12);
 588
 589	state = connector->state;
 590	KUNIT_EXPECT_EQ(test, state->max_bpc, 12);
 591	KUNIT_EXPECT_EQ(test, state->max_requested_bpc, 12);
 592
 593	prop = priv->drm.mode_config.hdr_output_metadata_property;
 594	KUNIT_ASSERT_NOT_NULL(test, prop);
 595	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
 596}
 597
 598/*
 599 * Test that the registration of an HDMI connector with no supported
 600 * format fails.
 601 */
 602static void drm_test_connector_hdmi_init_formats_empty(struct kunit *test)
 603{
 604	struct drm_connector_init_priv *priv = test->priv;
 605	int ret;
 606
 607	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 608				       "Vendor", "Product",
 609				       &dummy_funcs,
 610				       &dummy_hdmi_funcs,
 611				       DRM_MODE_CONNECTOR_HDMIA,
 612				       &priv->ddc,
 613				       0,
 614				       8);
 615	KUNIT_EXPECT_LT(test, ret, 0);
 616}
 617
 618/*
 619 * Test that the registration of an HDMI connector not listing RGB as a
 620 * supported format fails.
 621 */
 622static void drm_test_connector_hdmi_init_formats_no_rgb(struct kunit *test)
 623{
 624	struct drm_connector_init_priv *priv = test->priv;
 625	int ret;
 626
 627	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 628				       "Vendor", "Product",
 629				       &dummy_funcs,
 630				       &dummy_hdmi_funcs,
 631				       DRM_MODE_CONNECTOR_HDMIA,
 632				       &priv->ddc,
 633				       BIT(HDMI_COLORSPACE_YUV422),
 634				       8);
 635	KUNIT_EXPECT_LT(test, ret, 0);
 636}
 637
 638struct drm_connector_hdmi_init_formats_yuv420_allowed_test {
 639	unsigned long supported_formats;
 640	bool yuv420_allowed;
 641	int expected_result;
 642};
 643
 644#define YUV420_ALLOWED_TEST(_formats, _allowed, _result)			\
 645	{									\
 646		.supported_formats = BIT(HDMI_COLORSPACE_RGB) | (_formats),	\
 647		.yuv420_allowed = _allowed,					\
 648		.expected_result = _result,					\
 649	}
 650
 651static const struct drm_connector_hdmi_init_formats_yuv420_allowed_test
 652drm_connector_hdmi_init_formats_yuv420_allowed_tests[] = {
 653	YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV420), true, 0),
 654	YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV420), false, -EINVAL),
 655	YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV422), true, -EINVAL),
 656	YUV420_ALLOWED_TEST(BIT(HDMI_COLORSPACE_YUV422), false, 0),
 657};
 658
 659static void
 660drm_connector_hdmi_init_formats_yuv420_allowed_desc(const struct drm_connector_hdmi_init_formats_yuv420_allowed_test *t,
 661						    char *desc)
 662{
 663	sprintf(desc, "supported_formats=0x%lx yuv420_allowed=%d",
 664		t->supported_formats, t->yuv420_allowed);
 665}
 666
 667KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_formats_yuv420_allowed,
 668		  drm_connector_hdmi_init_formats_yuv420_allowed_tests,
 669		  drm_connector_hdmi_init_formats_yuv420_allowed_desc);
 670
 671/*
 672 * Test that the registration of an HDMI connector succeeds only when
 673 * the presence of YUV420 in the supported formats matches the value
 674 * of the ycbcr_420_allowed flag.
 675 */
 676static void drm_test_connector_hdmi_init_formats_yuv420_allowed(struct kunit *test)
 677{
 678	const struct drm_connector_hdmi_init_formats_yuv420_allowed_test *params;
 679	struct drm_connector_init_priv *priv = test->priv;
 680	int ret;
 681
 682	params = test->param_value;
 683	priv->connector.ycbcr_420_allowed = params->yuv420_allowed;
 684
 685	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 686				       "Vendor", "Product",
 687				       &dummy_funcs,
 688				       &dummy_hdmi_funcs,
 689				       DRM_MODE_CONNECTOR_HDMIA,
 690				       &priv->ddc,
 691				       params->supported_formats,
 692				       8);
 693	KUNIT_EXPECT_EQ(test, ret, params->expected_result);
 694}
 695
 696/*
 697 * Test that the registration of an HDMI connector with an HDMI
 698 * connector type succeeds.
 699 */
 700static void drm_test_connector_hdmi_init_type_valid(struct kunit *test)
 701{
 702	struct drm_connector_init_priv *priv = test->priv;
 703	unsigned int connector_type = *(unsigned int *)test->param_value;
 704	int ret;
 705
 706	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 707				       "Vendor", "Product",
 708				       &dummy_funcs,
 709				       &dummy_hdmi_funcs,
 710				       connector_type,
 711				       &priv->ddc,
 712				       BIT(HDMI_COLORSPACE_RGB),
 713				       8);
 714	KUNIT_EXPECT_EQ(test, ret, 0);
 715}
 716
 717static const unsigned int drm_connector_hdmi_init_type_valid_tests[] = {
 718	DRM_MODE_CONNECTOR_HDMIA,
 719	DRM_MODE_CONNECTOR_HDMIB,
 720};
 721
 722static void drm_connector_hdmi_init_type_desc(const unsigned int *type, char *desc)
 723{
 724	sprintf(desc, "%s", drm_get_connector_type_name(*type));
 725}
 726
 727KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_valid,
 728		  drm_connector_hdmi_init_type_valid_tests,
 729		  drm_connector_hdmi_init_type_desc);
 730
 731/*
 732 * Test that the registration of an HDMI connector with an !HDMI
 733 * connector type fails.
 734 */
 735static void drm_test_connector_hdmi_init_type_invalid(struct kunit *test)
 736{
 737	struct drm_connector_init_priv *priv = test->priv;
 738	unsigned int connector_type = *(unsigned int *)test->param_value;
 739	int ret;
 740
 741	ret = drmm_connector_hdmi_init(&priv->drm, &priv->connector,
 742				       "Vendor", "Product",
 743				       &dummy_funcs,
 744				       &dummy_hdmi_funcs,
 745				       connector_type,
 746				       &priv->ddc,
 747				       BIT(HDMI_COLORSPACE_RGB),
 748				       8);
 749	KUNIT_EXPECT_LT(test, ret, 0);
 750}
 751
 752static const unsigned int drm_connector_hdmi_init_type_invalid_tests[] = {
 753	DRM_MODE_CONNECTOR_Unknown,
 754	DRM_MODE_CONNECTOR_VGA,
 755	DRM_MODE_CONNECTOR_DVII,
 756	DRM_MODE_CONNECTOR_DVID,
 757	DRM_MODE_CONNECTOR_DVIA,
 758	DRM_MODE_CONNECTOR_Composite,
 759	DRM_MODE_CONNECTOR_SVIDEO,
 760	DRM_MODE_CONNECTOR_LVDS,
 761	DRM_MODE_CONNECTOR_Component,
 762	DRM_MODE_CONNECTOR_9PinDIN,
 763	DRM_MODE_CONNECTOR_DisplayPort,
 764	DRM_MODE_CONNECTOR_TV,
 765	DRM_MODE_CONNECTOR_eDP,
 766	DRM_MODE_CONNECTOR_VIRTUAL,
 767	DRM_MODE_CONNECTOR_DSI,
 768	DRM_MODE_CONNECTOR_DPI,
 769	DRM_MODE_CONNECTOR_WRITEBACK,
 770	DRM_MODE_CONNECTOR_SPI,
 771	DRM_MODE_CONNECTOR_USB,
 772};
 773
 774KUNIT_ARRAY_PARAM(drm_connector_hdmi_init_type_invalid,
 775		  drm_connector_hdmi_init_type_invalid_tests,
 776		  drm_connector_hdmi_init_type_desc);
 777
 778static struct kunit_case drmm_connector_hdmi_init_tests[] = {
 779	KUNIT_CASE(drm_test_connector_hdmi_init_valid),
 780	KUNIT_CASE(drm_test_connector_hdmi_init_bpc_8),
 781	KUNIT_CASE(drm_test_connector_hdmi_init_bpc_10),
 782	KUNIT_CASE(drm_test_connector_hdmi_init_bpc_12),
 783	KUNIT_CASE(drm_test_connector_hdmi_init_bpc_invalid),
 784	KUNIT_CASE(drm_test_connector_hdmi_init_bpc_null),
 785	KUNIT_CASE(drm_test_connector_hdmi_init_formats_empty),
 786	KUNIT_CASE(drm_test_connector_hdmi_init_formats_no_rgb),
 787	KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_formats_yuv420_allowed,
 788			 drm_connector_hdmi_init_formats_yuv420_allowed_gen_params),
 789	KUNIT_CASE(drm_test_connector_hdmi_init_null_ddc),
 790	KUNIT_CASE(drm_test_connector_hdmi_init_null_product),
 791	KUNIT_CASE(drm_test_connector_hdmi_init_null_vendor),
 792	KUNIT_CASE(drm_test_connector_hdmi_init_product_length_exact),
 793	KUNIT_CASE(drm_test_connector_hdmi_init_product_length_too_long),
 794	KUNIT_CASE(drm_test_connector_hdmi_init_product_valid),
 795	KUNIT_CASE(drm_test_connector_hdmi_init_vendor_length_exact),
 796	KUNIT_CASE(drm_test_connector_hdmi_init_vendor_length_too_long),
 797	KUNIT_CASE(drm_test_connector_hdmi_init_vendor_valid),
 798	KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_valid,
 799			 drm_connector_hdmi_init_type_valid_gen_params),
 800	KUNIT_CASE_PARAM(drm_test_connector_hdmi_init_type_invalid,
 801			 drm_connector_hdmi_init_type_invalid_gen_params),
 802	{ }
 803};
 804
 805static struct kunit_suite drmm_connector_hdmi_init_test_suite = {
 806	.name = "drmm_connector_hdmi_init",
 807	.init = drm_test_connector_init,
 808	.test_cases = drmm_connector_hdmi_init_tests,
 809};
 810
 811struct drm_get_tv_mode_from_name_test {
 812	const char *name;
 813	enum drm_connector_tv_mode expected_mode;
 814};
 815
 816#define TV_MODE_NAME(_name, _mode)		\
 817	{					\
 818		.name = _name,			\
 819		.expected_mode = _mode,		\
 820	}
 821
 822static void drm_test_get_tv_mode_from_name_valid(struct kunit *test)
 823{
 824	const struct drm_get_tv_mode_from_name_test *params = test->param_value;
 825
 826	KUNIT_EXPECT_EQ(test,
 827			drm_get_tv_mode_from_name(params->name, strlen(params->name)),
 828			params->expected_mode);
 829}
 830
 831static const
 832struct drm_get_tv_mode_from_name_test drm_get_tv_mode_from_name_valid_tests[] = {
 833	TV_MODE_NAME("NTSC", DRM_MODE_TV_MODE_NTSC),
 834	TV_MODE_NAME("NTSC-443", DRM_MODE_TV_MODE_NTSC_443),
 835	TV_MODE_NAME("NTSC-J", DRM_MODE_TV_MODE_NTSC_J),
 836	TV_MODE_NAME("PAL", DRM_MODE_TV_MODE_PAL),
 837	TV_MODE_NAME("PAL-M", DRM_MODE_TV_MODE_PAL_M),
 838	TV_MODE_NAME("PAL-N", DRM_MODE_TV_MODE_PAL_N),
 839	TV_MODE_NAME("SECAM", DRM_MODE_TV_MODE_SECAM),
 840	TV_MODE_NAME("Mono", DRM_MODE_TV_MODE_MONOCHROME),
 841};
 842
 843static void
 844drm_get_tv_mode_from_name_valid_desc(const struct drm_get_tv_mode_from_name_test *t,
 845				     char *desc)
 846{
 847	sprintf(desc, "%s", t->name);
 848}
 849
 850KUNIT_ARRAY_PARAM(drm_get_tv_mode_from_name_valid,
 851		  drm_get_tv_mode_from_name_valid_tests,
 852		  drm_get_tv_mode_from_name_valid_desc);
 853
 854static void drm_test_get_tv_mode_from_name_truncated(struct kunit *test)
 855{
 856	const char *name = "NTS";
 857	int ret;
 858
 859	ret = drm_get_tv_mode_from_name(name, strlen(name));
 860	KUNIT_EXPECT_LT(test, ret, 0);
 861};
 862
 863static struct kunit_case drm_get_tv_mode_from_name_tests[] = {
 864	KUNIT_CASE_PARAM(drm_test_get_tv_mode_from_name_valid,
 865			 drm_get_tv_mode_from_name_valid_gen_params),
 866	KUNIT_CASE(drm_test_get_tv_mode_from_name_truncated),
 867	{ }
 868};
 869
 870static struct kunit_suite drm_get_tv_mode_from_name_test_suite = {
 871	.name = "drm_get_tv_mode_from_name",
 872	.test_cases = drm_get_tv_mode_from_name_tests,
 873};
 874
 875struct drm_hdmi_connector_get_broadcast_rgb_name_test {
 876	unsigned int kind;
 877	const char *expected_name;
 878};
 879
 880#define BROADCAST_RGB_TEST(_kind, _name)	\
 881	{					\
 882		.kind = _kind,			\
 883		.expected_name = _name,		\
 884	}
 885
 886static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name(struct kunit *test)
 887{
 888	const struct drm_hdmi_connector_get_broadcast_rgb_name_test *params =
 889		test->param_value;
 890
 891	KUNIT_EXPECT_STREQ(test,
 892			   drm_hdmi_connector_get_broadcast_rgb_name(params->kind),
 893			   params->expected_name);
 894}
 895
 896static const
 897struct drm_hdmi_connector_get_broadcast_rgb_name_test
 898drm_hdmi_connector_get_broadcast_rgb_name_valid_tests[] = {
 899	BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_AUTO, "Automatic"),
 900	BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_FULL, "Full"),
 901	BROADCAST_RGB_TEST(DRM_HDMI_BROADCAST_RGB_LIMITED, "Limited 16:235"),
 902};
 903
 904static void
 905drm_hdmi_connector_get_broadcast_rgb_name_valid_desc(const struct drm_hdmi_connector_get_broadcast_rgb_name_test *t,
 906						     char *desc)
 907{
 908	sprintf(desc, "%s", t->expected_name);
 909}
 910
 911KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_broadcast_rgb_name_valid,
 912		  drm_hdmi_connector_get_broadcast_rgb_name_valid_tests,
 913		  drm_hdmi_connector_get_broadcast_rgb_name_valid_desc);
 914
 915static void drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid(struct kunit *test)
 916{
 917	KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_broadcast_rgb_name(3));
 918};
 919
 920static struct kunit_case drm_hdmi_connector_get_broadcast_rgb_name_tests[] = {
 921	KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_broadcast_rgb_name,
 922			 drm_hdmi_connector_get_broadcast_rgb_name_valid_gen_params),
 923	KUNIT_CASE(drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid),
 924	{ }
 925};
 926
 927static struct kunit_suite drm_hdmi_connector_get_broadcast_rgb_name_test_suite = {
 928	.name = "drm_hdmi_connector_get_broadcast_rgb_name",
 929	.test_cases = drm_hdmi_connector_get_broadcast_rgb_name_tests,
 930};
 931
 932struct drm_hdmi_connector_get_output_format_name_test {
 933	unsigned int kind;
 934	const char *expected_name;
 935};
 936
 937#define OUTPUT_FORMAT_TEST(_kind, _name)	\
 938	{					\
 939		.kind = _kind,			\
 940		.expected_name = _name,		\
 941	}
 942
 943static void drm_test_drm_hdmi_connector_get_output_format_name(struct kunit *test)
 944{
 945	const struct drm_hdmi_connector_get_output_format_name_test *params =
 946		test->param_value;
 947
 948	KUNIT_EXPECT_STREQ(test,
 949			   drm_hdmi_connector_get_output_format_name(params->kind),
 950			   params->expected_name);
 951}
 952
 953static const
 954struct drm_hdmi_connector_get_output_format_name_test
 955drm_hdmi_connector_get_output_format_name_valid_tests[] = {
 956	OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_RGB, "RGB"),
 957	OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV420, "YUV 4:2:0"),
 958	OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV422, "YUV 4:2:2"),
 959	OUTPUT_FORMAT_TEST(HDMI_COLORSPACE_YUV444, "YUV 4:4:4"),
 960};
 961
 962static void
 963drm_hdmi_connector_get_output_format_name_valid_desc(const struct drm_hdmi_connector_get_output_format_name_test *t,
 964						     char *desc)
 965{
 966	sprintf(desc, "%s", t->expected_name);
 967}
 968
 969KUNIT_ARRAY_PARAM(drm_hdmi_connector_get_output_format_name_valid,
 970		  drm_hdmi_connector_get_output_format_name_valid_tests,
 971		  drm_hdmi_connector_get_output_format_name_valid_desc);
 972
 973static void drm_test_drm_hdmi_connector_get_output_format_name_invalid(struct kunit *test)
 974{
 975	KUNIT_EXPECT_NULL(test, drm_hdmi_connector_get_output_format_name(4));
 976};
 977
 978static struct kunit_case drm_hdmi_connector_get_output_format_name_tests[] = {
 979	KUNIT_CASE_PARAM(drm_test_drm_hdmi_connector_get_output_format_name,
 980			 drm_hdmi_connector_get_output_format_name_valid_gen_params),
 981	KUNIT_CASE(drm_test_drm_hdmi_connector_get_output_format_name_invalid),
 982	{ }
 983};
 984
 985static struct kunit_suite drm_hdmi_connector_get_output_format_name_test_suite = {
 986	.name = "drm_hdmi_connector_get_output_format_name",
 987	.test_cases = drm_hdmi_connector_get_output_format_name_tests,
 988};
 989
 990static void drm_test_drm_connector_attach_broadcast_rgb_property(struct kunit *test)
 991{
 992	struct drm_connector_init_priv *priv = test->priv;
 993	struct drm_connector *connector = &priv->connector;
 994	struct drm_property *prop;
 995	int ret;
 996
 997	ret = drmm_connector_init(&priv->drm, connector,
 998				  &dummy_funcs,
 999				  DRM_MODE_CONNECTOR_HDMIA,
1000				  &priv->ddc);
1001	KUNIT_ASSERT_EQ(test, ret, 0);
1002
1003	ret = drm_connector_attach_broadcast_rgb_property(connector);
1004	KUNIT_ASSERT_EQ(test, ret, 0);
1005
1006	prop = connector->broadcast_rgb_property;
1007	KUNIT_ASSERT_NOT_NULL(test, prop);
1008	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
1009}
1010
1011static void drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector(struct kunit *test)
1012{
1013	struct drm_connector_init_priv *priv = test->priv;
1014	struct drm_connector *connector = &priv->connector;
1015	struct drm_property *prop;
1016	int ret;
1017
1018	ret = drmm_connector_hdmi_init(&priv->drm, connector,
1019				       "Vendor", "Product",
1020				       &dummy_funcs,
1021				       &dummy_hdmi_funcs,
1022				       DRM_MODE_CONNECTOR_HDMIA,
1023				       &priv->ddc,
1024				       BIT(HDMI_COLORSPACE_RGB),
1025				       8);
1026	KUNIT_EXPECT_EQ(test, ret, 0);
1027
1028	ret = drm_connector_attach_broadcast_rgb_property(connector);
1029	KUNIT_ASSERT_EQ(test, ret, 0);
1030
1031	prop = connector->broadcast_rgb_property;
1032	KUNIT_ASSERT_NOT_NULL(test, prop);
1033	KUNIT_EXPECT_NOT_NULL(test, drm_mode_obj_find_prop_id(&connector->base, prop->base.id));
1034}
1035
1036static struct kunit_case drm_connector_attach_broadcast_rgb_property_tests[] = {
1037	KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property),
1038	KUNIT_CASE(drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector),
1039	{ }
1040};
1041
1042static struct kunit_suite drm_connector_attach_broadcast_rgb_property_test_suite = {
1043	.name = "drm_connector_attach_broadcast_rgb_property",
1044	.init = drm_test_connector_init,
1045	.test_cases = drm_connector_attach_broadcast_rgb_property_tests,
1046};
1047
1048/*
1049 * Test that for a given mode, with 8bpc and an RGB output the TMDS
1050 * character rate is equal to the mode pixel clock.
1051 */
1052static void drm_test_drm_hdmi_compute_mode_clock_rgb(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, 8, HDMI_COLORSPACE_RGB);
1065	KUNIT_ASSERT_GT(test, rate, 0);
1066	KUNIT_EXPECT_EQ(test, mode->clock * 1000ULL, rate);
1067}
1068
1069/*
1070 * Test that for a given mode, with 10bpc and an RGB output the TMDS
1071 * character rate is equal to 1.25 times the mode pixel clock.
1072 */
1073static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc(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, 16);
1081	KUNIT_ASSERT_NOT_NULL(test, mode);
1082
1083	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1084
1085	rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
1086	KUNIT_ASSERT_GT(test, rate, 0);
1087	KUNIT_EXPECT_EQ(test, mode->clock * 1250, rate);
1088}
1089
1090/*
1091 * Test that for the VIC-1 mode, with 10bpc and an RGB output the TMDS
1092 * character rate computation fails.
1093 */
1094static void drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1(struct kunit *test)
1095{
1096	struct drm_connector_init_priv *priv = test->priv;
1097	const struct drm_display_mode *mode;
1098	unsigned long long rate;
1099	struct drm_device *drm = &priv->drm;
1100
1101	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
1102	KUNIT_ASSERT_NOT_NULL(test, mode);
1103
1104	rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_RGB);
1105	KUNIT_EXPECT_EQ(test, rate, 0);
1106}
1107
1108/*
1109 * Test that for a given mode, with 12bpc and an RGB output the TMDS
1110 * character rate is equal to 1.5 times the mode pixel clock.
1111 */
1112static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc(struct kunit *test)
1113{
1114	struct drm_connector_init_priv *priv = test->priv;
1115	const struct drm_display_mode *mode;
1116	unsigned long long rate;
1117	struct drm_device *drm = &priv->drm;
1118
1119	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1120	KUNIT_ASSERT_NOT_NULL(test, mode);
1121
1122	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1123
1124	rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
1125	KUNIT_ASSERT_GT(test, rate, 0);
1126	KUNIT_EXPECT_EQ(test, mode->clock * 1500, rate);
1127}
1128
1129/*
1130 * Test that for the VIC-1 mode, with 12bpc and an RGB output the TMDS
1131 * character rate computation fails.
1132 */
1133static void drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1(struct kunit *test)
1134{
1135	struct drm_connector_init_priv *priv = test->priv;
1136	const struct drm_display_mode *mode;
1137	unsigned long long rate;
1138	struct drm_device *drm = &priv->drm;
1139
1140	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 1);
1141	KUNIT_ASSERT_NOT_NULL(test, mode);
1142
1143	rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_RGB);
1144	KUNIT_EXPECT_EQ(test, rate, 0);
1145}
1146
1147/*
1148 * Test that for a mode with the pixel repetition flag, the TMDS
1149 * character rate is indeed double the mode pixel clock.
1150 */
1151static void drm_test_drm_hdmi_compute_mode_clock_rgb_double(struct kunit *test)
1152{
1153	struct drm_connector_init_priv *priv = test->priv;
1154	const struct drm_display_mode *mode;
1155	unsigned long long rate;
1156	struct drm_device *drm = &priv->drm;
1157
1158	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 6);
1159	KUNIT_ASSERT_NOT_NULL(test, mode);
1160
1161	KUNIT_ASSERT_TRUE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1162
1163	rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
1164	KUNIT_ASSERT_GT(test, rate, 0);
1165	KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) * 2, rate);
1166}
1167
1168/*
1169 * Test that the TMDS character rate computation for the VIC modes
1170 * explicitly listed in the spec as supporting YUV420 succeed and return
1171 * half the mode pixel clock.
1172 */
1173static void drm_test_connector_hdmi_compute_mode_clock_yuv420_valid(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 long long rate;
1179	unsigned int vic = *(unsigned int *)test->param_value;
1180
1181	mode = drm_kunit_display_mode_from_cea_vic(test, drm, vic);
1182	KUNIT_ASSERT_NOT_NULL(test, mode);
1183
1184	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1185
1186	rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV420);
1187	KUNIT_ASSERT_GT(test, rate, 0);
1188	KUNIT_EXPECT_EQ(test, (mode->clock * 1000ULL) / 2, rate);
1189}
1190
1191static const unsigned int drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[] = {
1192	96, 97, 101, 102, 106, 107,
1193};
1194
1195static void drm_hdmi_compute_mode_clock_yuv420_vic_desc(const unsigned int *vic, char *desc)
1196{
1197	sprintf(desc, "VIC %u", *vic);
1198}
1199
1200KUNIT_ARRAY_PARAM(drm_hdmi_compute_mode_clock_yuv420_valid,
1201		  drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests,
1202		  drm_hdmi_compute_mode_clock_yuv420_vic_desc);
1203
1204/*
1205 * Test that for a given mode listed supporting it and an YUV420 output
1206 * with 10bpc, the TMDS character rate is equal to 0.625 times the mode
1207 * pixel clock.
1208 */
1209static void drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc(struct kunit *test)
1210{
1211	struct drm_connector_init_priv *priv = test->priv;
1212	const struct drm_display_mode *mode;
1213	struct drm_device *drm = &priv->drm;
1214	unsigned int vic =
1215		drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0];
1216	unsigned long long rate;
1217
1218	mode = drm_kunit_display_mode_from_cea_vic(test, drm, vic);
1219	KUNIT_ASSERT_NOT_NULL(test, mode);
1220
1221	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1222
1223	rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV420);
1224	KUNIT_ASSERT_GT(test, rate, 0);
1225
1226	KUNIT_EXPECT_EQ(test, mode->clock * 625, rate);
1227}
1228
1229/*
1230 * Test that for a given mode listed supporting it and an YUV420 output
1231 * with 12bpc, the TMDS character rate is equal to 0.75 times the mode
1232 * pixel clock.
1233 */
1234static void drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc(struct kunit *test)
1235{
1236	struct drm_connector_init_priv *priv = test->priv;
1237	const struct drm_display_mode *mode;
1238	struct drm_device *drm = &priv->drm;
1239	unsigned int vic =
1240		drm_hdmi_compute_mode_clock_yuv420_vic_valid_tests[0];
1241	unsigned long long rate;
1242
1243	mode = drm_kunit_display_mode_from_cea_vic(test, drm, vic);
1244	KUNIT_ASSERT_NOT_NULL(test, mode);
1245
1246	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1247
1248	rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV420);
1249	KUNIT_ASSERT_GT(test, rate, 0);
1250
1251	KUNIT_EXPECT_EQ(test, mode->clock * 750, rate);
1252}
1253
1254/*
1255 * Test that for a given mode, the computation of the TMDS character
1256 * rate with 8bpc and a YUV422 output succeeds and returns a rate equal
1257 * to the mode pixel clock.
1258 */
1259static void drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc(struct kunit *test)
1260{
1261	struct drm_connector_init_priv *priv = test->priv;
1262	const struct drm_display_mode *mode;
1263	struct drm_device *drm = &priv->drm;
1264	unsigned long long rate;
1265
1266	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1267	KUNIT_ASSERT_NOT_NULL(test, mode);
1268
1269	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1270
1271	rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_YUV422);
1272	KUNIT_ASSERT_GT(test, rate, 0);
1273	KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1274}
1275
1276/*
1277 * Test that for a given mode, the computation of the TMDS character
1278 * rate with 10bpc and a YUV422 output succeeds and returns a rate equal
1279 * to the mode pixel clock.
1280 */
1281static void drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc(struct kunit *test)
1282{
1283	struct drm_connector_init_priv *priv = test->priv;
1284	const struct drm_display_mode *mode;
1285	struct drm_device *drm = &priv->drm;
1286	unsigned long long rate;
1287
1288	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1289	KUNIT_ASSERT_NOT_NULL(test, mode);
1290
1291	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1292
1293	rate = drm_hdmi_compute_mode_clock(mode, 10, HDMI_COLORSPACE_YUV422);
1294	KUNIT_ASSERT_GT(test, rate, 0);
1295	KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1296}
1297
1298/*
1299 * Test that for a given mode, the computation of the TMDS character
1300 * rate with 12bpc and a YUV422 output succeeds and returns a rate equal
1301 * to the mode pixel clock.
1302 */
1303static void drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc(struct kunit *test)
1304{
1305	struct drm_connector_init_priv *priv = test->priv;
1306	const struct drm_display_mode *mode;
1307	struct drm_device *drm = &priv->drm;
1308	unsigned long long rate;
1309
1310	mode = drm_kunit_display_mode_from_cea_vic(test, drm, 16);
1311	KUNIT_ASSERT_NOT_NULL(test, mode);
1312
1313	KUNIT_ASSERT_FALSE(test, mode->flags & DRM_MODE_FLAG_DBLCLK);
1314
1315	rate = drm_hdmi_compute_mode_clock(mode, 12, HDMI_COLORSPACE_YUV422);
1316	KUNIT_ASSERT_GT(test, rate, 0);
1317	KUNIT_EXPECT_EQ(test, mode->clock * 1000, rate);
1318}
1319
1320static struct kunit_case drm_hdmi_compute_mode_clock_tests[] = {
1321	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb),
1322	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc),
1323	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1),
1324	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc),
1325	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1),
1326	KUNIT_CASE(drm_test_drm_hdmi_compute_mode_clock_rgb_double),
1327	KUNIT_CASE_PARAM(drm_test_connector_hdmi_compute_mode_clock_yuv420_valid,
1328			 drm_hdmi_compute_mode_clock_yuv420_valid_gen_params),
1329	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc),
1330	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc),
1331	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc),
1332	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc),
1333	KUNIT_CASE(drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc),
1334	{ }
1335};
1336
1337static struct kunit_suite drm_hdmi_compute_mode_clock_test_suite = {
1338	.name = "drm_test_connector_hdmi_compute_mode_clock",
1339	.init = drm_test_connector_init,
1340	.test_cases = drm_hdmi_compute_mode_clock_tests,
1341};
1342
1343kunit_test_suites(
1344	&drmm_connector_hdmi_init_test_suite,
1345	&drmm_connector_init_test_suite,
1346	&drm_connector_attach_broadcast_rgb_property_test_suite,
1347	&drm_get_tv_mode_from_name_test_suite,
1348	&drm_hdmi_compute_mode_clock_test_suite,
1349	&drm_hdmi_connector_get_broadcast_rgb_name_test_suite,
1350	&drm_hdmi_connector_get_output_format_name_test_suite
1351);
1352
1353MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
1354MODULE_DESCRIPTION("Kunit test for drm_modes functions");
1355MODULE_LICENSE("GPL");