drm_client_modeset_test.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2022 Maxime Ripard <mripard@kernel.org>
  4. */
  5. #include <kunit/test.h>
  6. #include <drm/drm_connector.h>
  7. #include <drm/drm_edid.h>
  8. #include <drm/drm_drv.h>
  9. #include <drm/drm_kunit_helpers.h>
  10. #include <drm/drm_modes.h>
  11. #include <drm/drm_modeset_helper_vtables.h>
  12. #include <drm/drm_probe_helper.h>
  13. struct drm_client_modeset_test_priv {
  14. struct drm_device *drm;
  15. struct device *dev;
  16. struct drm_connector connector;
  17. };
  18. static int drm_client_modeset_connector_get_modes(struct drm_connector *connector)
  19. {
  20. struct drm_display_mode *mode;
  21. int count;
  22. count = drm_add_modes_noedid(connector, 1920, 1200);
  23. mode = drm_mode_analog_ntsc_480i(connector->dev);
  24. if (!mode)
  25. return count;
  26. drm_mode_probed_add(connector, mode);
  27. count += 1;
  28. mode = drm_mode_analog_pal_576i(connector->dev);
  29. if (!mode)
  30. return count;
  31. drm_mode_probed_add(connector, mode);
  32. count += 1;
  33. return count;
  34. }
  35. static const struct drm_connector_helper_funcs drm_client_modeset_connector_helper_funcs = {
  36. .get_modes = drm_client_modeset_connector_get_modes,
  37. };
  38. static const struct drm_connector_funcs drm_client_modeset_connector_funcs = {
  39. };
  40. static int drm_client_modeset_test_init(struct kunit *test)
  41. {
  42. struct drm_client_modeset_test_priv *priv;
  43. int ret;
  44. priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
  45. KUNIT_ASSERT_NOT_NULL(test, priv);
  46. test->priv = priv;
  47. priv->dev = drm_kunit_helper_alloc_device(test);
  48. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev);
  49. priv->drm = __drm_kunit_helper_alloc_drm_device(test, priv->dev,
  50. sizeof(*priv->drm), 0,
  51. DRIVER_MODESET);
  52. KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm);
  53. ret = drmm_connector_init(priv->drm, &priv->connector,
  54. &drm_client_modeset_connector_funcs,
  55. DRM_MODE_CONNECTOR_Unknown,
  56. NULL);
  57. KUNIT_ASSERT_EQ(test, ret, 0);
  58. drm_connector_helper_add(&priv->connector, &drm_client_modeset_connector_helper_funcs);
  59. priv->connector.interlace_allowed = true;
  60. priv->connector.doublescan_allowed = true;
  61. return 0;
  62. }
  63. static void drm_test_pick_cmdline_res_1920_1080_60(struct kunit *test)
  64. {
  65. struct drm_client_modeset_test_priv *priv = test->priv;
  66. struct drm_device *drm = priv->drm;
  67. struct drm_connector *connector = &priv->connector;
  68. struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
  69. struct drm_display_mode *expected_mode, *mode;
  70. const char *cmdline = "1920x1080@60";
  71. int ret;
  72. expected_mode = drm_mode_find_dmt(priv->drm, 1920, 1080, 60, false);
  73. KUNIT_ASSERT_NOT_NULL(test, expected_mode);
  74. ret = drm_kunit_add_mode_destroy_action(test, expected_mode);
  75. KUNIT_ASSERT_EQ(test, ret, 0);
  76. KUNIT_ASSERT_TRUE(test,
  77. drm_mode_parse_command_line_for_connector(cmdline,
  78. connector,
  79. cmdline_mode));
  80. mutex_lock(&drm->mode_config.mutex);
  81. ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
  82. mutex_unlock(&drm->mode_config.mutex);
  83. KUNIT_ASSERT_GT(test, ret, 0);
  84. mode = drm_connector_pick_cmdline_mode(connector);
  85. KUNIT_ASSERT_NOT_NULL(test, mode);
  86. KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected_mode, mode));
  87. }
  88. struct drm_connector_pick_cmdline_mode_test {
  89. const char *cmdline;
  90. struct drm_display_mode *(*func)(struct drm_device *drm);
  91. };
  92. #define TEST_CMDLINE(_cmdline, _fn) \
  93. { \
  94. .cmdline = _cmdline, \
  95. .func = _fn, \
  96. }
  97. static void drm_test_pick_cmdline_named(struct kunit *test)
  98. {
  99. const struct drm_connector_pick_cmdline_mode_test *params = test->param_value;
  100. struct drm_client_modeset_test_priv *priv = test->priv;
  101. struct drm_device *drm = priv->drm;
  102. struct drm_connector *connector = &priv->connector;
  103. struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
  104. const struct drm_display_mode *expected_mode, *mode;
  105. const char *cmdline = params->cmdline;
  106. int ret;
  107. KUNIT_ASSERT_TRUE(test,
  108. drm_mode_parse_command_line_for_connector(cmdline,
  109. connector,
  110. cmdline_mode));
  111. mutex_lock(&drm->mode_config.mutex);
  112. ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
  113. mutex_unlock(&drm->mode_config.mutex);
  114. KUNIT_ASSERT_GT(test, ret, 0);
  115. mode = drm_connector_pick_cmdline_mode(connector);
  116. KUNIT_ASSERT_NOT_NULL(test, mode);
  117. expected_mode = params->func(drm);
  118. KUNIT_ASSERT_NOT_NULL(test, expected_mode);
  119. KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected_mode, mode));
  120. }
  121. static const
  122. struct drm_connector_pick_cmdline_mode_test drm_connector_pick_cmdline_mode_tests[] = {
  123. TEST_CMDLINE("NTSC", drm_mode_analog_ntsc_480i),
  124. TEST_CMDLINE("NTSC-J", drm_mode_analog_ntsc_480i),
  125. TEST_CMDLINE("PAL", drm_mode_analog_pal_576i),
  126. TEST_CMDLINE("PAL-M", drm_mode_analog_ntsc_480i),
  127. };
  128. static void
  129. drm_connector_pick_cmdline_mode_desc(const struct drm_connector_pick_cmdline_mode_test *t,
  130. char *desc)
  131. {
  132. sprintf(desc, "%s", t->cmdline);
  133. }
  134. KUNIT_ARRAY_PARAM(drm_connector_pick_cmdline_mode,
  135. drm_connector_pick_cmdline_mode_tests,
  136. drm_connector_pick_cmdline_mode_desc);
  137. static struct kunit_case drm_test_pick_cmdline_tests[] = {
  138. KUNIT_CASE(drm_test_pick_cmdline_res_1920_1080_60),
  139. KUNIT_CASE_PARAM(drm_test_pick_cmdline_named,
  140. drm_connector_pick_cmdline_mode_gen_params),
  141. {}
  142. };
  143. static struct kunit_suite drm_test_pick_cmdline_test_suite = {
  144. .name = "drm_test_pick_cmdline",
  145. .init = drm_client_modeset_test_init,
  146. .test_cases = drm_test_pick_cmdline_tests
  147. };
  148. kunit_test_suite(drm_test_pick_cmdline_test_suite);
  149. /*
  150. * This file is included directly by drm_client_modeset.c so we can't
  151. * use any MODULE_* macro here.
  152. */