1 // SPDX-License-Identifier: GPL-2.0
3 * Kunit test for drm_probe_helper functions
6 #include <drm/drm_atomic_state_helper.h>
7 #include <drm/drm_connector.h>
8 #include <drm/drm_device.h>
9 #include <drm/drm_drv.h>
10 #include <drm/drm_kunit_helpers.h>
11 #include <drm/drm_mode.h>
12 #include <drm/drm_modes.h>
13 #include <drm/drm_modeset_helper_vtables.h>
14 #include <drm/drm_probe_helper.h>
16 #include <kunit/test.h>
18 struct drm_probe_helper_test_priv {
19 struct drm_device *drm;
21 struct drm_connector connector;
24 static const struct drm_connector_helper_funcs drm_probe_helper_connector_helper_funcs = {
27 static const struct drm_connector_funcs drm_probe_helper_connector_funcs = {
28 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
29 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
30 .reset = drm_atomic_helper_connector_reset,
33 static int drm_probe_helper_test_init(struct kunit *test)
35 struct drm_probe_helper_test_priv *priv;
36 struct drm_connector *connector;
39 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
40 KUNIT_ASSERT_NOT_NULL(test, priv);
43 priv->dev = drm_kunit_helper_alloc_device(test);
44 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev);
46 priv->drm = __drm_kunit_helper_alloc_drm_device(test, priv->dev,
47 sizeof(*priv->drm), 0,
48 DRIVER_MODESET | DRIVER_ATOMIC);
49 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm);
51 connector = &priv->connector;
52 ret = drmm_connector_init(priv->drm, connector,
53 &drm_probe_helper_connector_funcs,
54 DRM_MODE_CONNECTOR_Unknown,
56 KUNIT_ASSERT_EQ(test, ret, 0);
58 drm_connector_helper_add(connector, &drm_probe_helper_connector_helper_funcs);
63 static void drm_probe_helper_test_exit(struct kunit *test)
65 struct drm_probe_helper_test_priv *priv = test->priv;
67 drm_kunit_helper_free_device(test, priv->dev);
70 typedef struct drm_display_mode *(*expected_mode_func_t)(struct drm_device *);
72 struct drm_connector_helper_tv_get_modes_test {
74 unsigned int supported_tv_modes;
75 enum drm_connector_tv_mode default_mode;
77 enum drm_connector_tv_mode cmdline_mode;
78 expected_mode_func_t *expected_modes;
79 unsigned int num_expected_modes;
82 #define _TV_MODE_TEST(_name, _supported, _default, _cmdline, _cmdline_mode, ...) \
85 .supported_tv_modes = _supported, \
86 .default_mode = _default, \
87 .cmdline = _cmdline, \
88 .cmdline_mode = _cmdline_mode, \
89 .expected_modes = (expected_mode_func_t[]) { __VA_ARGS__ }, \
90 .num_expected_modes = sizeof((expected_mode_func_t[]) { __VA_ARGS__ }) / \
91 (sizeof(expected_mode_func_t)), \
94 #define TV_MODE_TEST(_name, _supported, _default, ...) \
95 _TV_MODE_TEST(_name, _supported, _default, false, 0, __VA_ARGS__)
97 #define TV_MODE_TEST_CMDLINE(_name, _supported, _default, _cmdline, ...) \
98 _TV_MODE_TEST(_name, _supported, _default, true, _cmdline, __VA_ARGS__)
101 drm_test_connector_helper_tv_get_modes_check(struct kunit *test)
103 const struct drm_connector_helper_tv_get_modes_test *params = test->param_value;
104 struct drm_probe_helper_test_priv *priv = test->priv;
105 struct drm_connector *connector = &priv->connector;
106 struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
107 struct drm_display_mode *mode;
108 const struct drm_display_mode *expected;
112 if (params->cmdline) {
113 cmdline->tv_mode_specified = true;
114 cmdline->tv_mode = params->cmdline_mode;
117 ret = drm_mode_create_tv_properties(priv->drm, params->supported_tv_modes);
118 KUNIT_ASSERT_EQ(test, ret, 0);
120 drm_object_attach_property(&connector->base,
121 priv->drm->mode_config.tv_mode_property,
122 params->default_mode);
124 mutex_lock(&priv->drm->mode_config.mutex);
126 ret = drm_connector_helper_tv_get_modes(connector);
127 KUNIT_EXPECT_EQ(test, ret, params->num_expected_modes);
130 list_for_each_entry(mode, &connector->probed_modes, head)
132 KUNIT_EXPECT_EQ(test, len, params->num_expected_modes);
134 if (params->num_expected_modes >= 1) {
135 mode = list_first_entry_or_null(&connector->probed_modes,
136 struct drm_display_mode, head);
137 KUNIT_ASSERT_NOT_NULL(test, mode);
139 expected = params->expected_modes[0](priv->drm);
140 KUNIT_ASSERT_NOT_NULL(test, expected);
142 KUNIT_EXPECT_TRUE(test, drm_mode_equal(mode, expected));
143 KUNIT_EXPECT_TRUE(test, mode->type & DRM_MODE_TYPE_PREFERRED);
146 if (params->num_expected_modes >= 2) {
147 mode = list_next_entry(mode, head);
148 KUNIT_ASSERT_NOT_NULL(test, mode);
150 expected = params->expected_modes[1](priv->drm);
151 KUNIT_ASSERT_NOT_NULL(test, expected);
153 KUNIT_EXPECT_TRUE(test, drm_mode_equal(mode, expected));
154 KUNIT_EXPECT_FALSE(test, mode->type & DRM_MODE_TYPE_PREFERRED);
157 mutex_unlock(&priv->drm->mode_config.mutex);
161 struct drm_connector_helper_tv_get_modes_test drm_connector_helper_tv_get_modes_tests[] = {
164 BIT(DRM_MODE_TV_MODE_PAL),
165 DRM_MODE_TV_MODE_PAL,
166 drm_mode_analog_pal_576i),
168 BIT(DRM_MODE_TV_MODE_NTSC),
169 DRM_MODE_TV_MODE_NTSC,
170 drm_mode_analog_ntsc_480i),
171 TV_MODE_TEST("Both, NTSC Default",
172 BIT(DRM_MODE_TV_MODE_NTSC) | BIT(DRM_MODE_TV_MODE_PAL),
173 DRM_MODE_TV_MODE_NTSC,
174 drm_mode_analog_ntsc_480i, drm_mode_analog_pal_576i),
175 TV_MODE_TEST("Both, PAL Default",
176 BIT(DRM_MODE_TV_MODE_NTSC) | BIT(DRM_MODE_TV_MODE_PAL),
177 DRM_MODE_TV_MODE_PAL,
178 drm_mode_analog_pal_576i, drm_mode_analog_ntsc_480i),
179 TV_MODE_TEST_CMDLINE("Both, NTSC Default, with PAL on command-line",
180 BIT(DRM_MODE_TV_MODE_NTSC) | BIT(DRM_MODE_TV_MODE_PAL),
181 DRM_MODE_TV_MODE_NTSC,
182 DRM_MODE_TV_MODE_PAL,
183 drm_mode_analog_pal_576i, drm_mode_analog_ntsc_480i),
184 TV_MODE_TEST_CMDLINE("Both, PAL Default, with NTSC on command-line",
185 BIT(DRM_MODE_TV_MODE_NTSC) | BIT(DRM_MODE_TV_MODE_PAL),
186 DRM_MODE_TV_MODE_PAL,
187 DRM_MODE_TV_MODE_NTSC,
188 drm_mode_analog_ntsc_480i, drm_mode_analog_pal_576i),
192 drm_connector_helper_tv_get_modes_desc(const struct drm_connector_helper_tv_get_modes_test *t,
195 sprintf(desc, "%s", t->name);
198 KUNIT_ARRAY_PARAM(drm_connector_helper_tv_get_modes,
199 drm_connector_helper_tv_get_modes_tests,
200 drm_connector_helper_tv_get_modes_desc);
202 static struct kunit_case drm_test_connector_helper_tv_get_modes_tests[] = {
203 KUNIT_CASE_PARAM(drm_test_connector_helper_tv_get_modes_check,
204 drm_connector_helper_tv_get_modes_gen_params),
208 static struct kunit_suite drm_test_connector_helper_tv_get_modes_suite = {
209 .name = "drm_connector_helper_tv_get_modes",
210 .init = drm_probe_helper_test_init,
211 .exit = drm_probe_helper_test_exit,
212 .test_cases = drm_test_connector_helper_tv_get_modes_tests,
215 kunit_test_suite(drm_test_connector_helper_tv_get_modes_suite);
218 MODULE_LICENSE("GPL");