Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Kunit test for drm_probe_helper functions
4 : */
5 :
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>
15 :
16 : #include <kunit/test.h>
17 :
18 : struct drm_probe_helper_test_priv {
19 : struct drm_device *drm;
20 : struct device *dev;
21 : struct drm_connector connector;
22 : };
23 :
24 : static const struct drm_connector_helper_funcs drm_probe_helper_connector_helper_funcs = {
25 : };
26 :
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,
31 : };
32 :
33 7 : static int drm_probe_helper_test_init(struct kunit *test)
34 : {
35 : struct drm_probe_helper_test_priv *priv;
36 : struct drm_connector *connector;
37 : int ret;
38 :
39 7 : priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
40 7 : KUNIT_ASSERT_NOT_NULL(test, priv);
41 7 : test->priv = priv;
42 :
43 7 : priv->dev = drm_kunit_helper_alloc_device(test);
44 14 : KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev);
45 :
46 7 : priv->drm = __drm_kunit_helper_alloc_drm_device(test, priv->dev,
47 : sizeof(*priv->drm), 0,
48 : DRIVER_MODESET | DRIVER_ATOMIC);
49 14 : KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm);
50 :
51 7 : connector = &priv->connector;
52 7 : ret = drmm_connector_init(priv->drm, connector,
53 : &drm_probe_helper_connector_funcs,
54 : DRM_MODE_CONNECTOR_Unknown,
55 : NULL);
56 7 : KUNIT_ASSERT_EQ(test, ret, 0);
57 :
58 14 : drm_connector_helper_add(connector, &drm_probe_helper_connector_helper_funcs);
59 :
60 7 : return 0;
61 : }
62 :
63 7 : static void drm_probe_helper_test_exit(struct kunit *test)
64 : {
65 7 : struct drm_probe_helper_test_priv *priv = test->priv;
66 :
67 7 : drm_kunit_helper_free_device(test, priv->dev);
68 7 : }
69 :
70 : typedef struct drm_display_mode *(*expected_mode_func_t)(struct drm_device *);
71 :
72 : struct drm_connector_helper_tv_get_modes_test {
73 : const char *name;
74 : unsigned int supported_tv_modes;
75 : enum drm_connector_tv_mode default_mode;
76 : bool cmdline;
77 : enum drm_connector_tv_mode cmdline_mode;
78 : expected_mode_func_t *expected_modes;
79 : unsigned int num_expected_modes;
80 : };
81 :
82 : #define _TV_MODE_TEST(_name, _supported, _default, _cmdline, _cmdline_mode, ...) \
83 : { \
84 : .name = _name, \
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)), \
92 : }
93 :
94 : #define TV_MODE_TEST(_name, _supported, _default, ...) \
95 : _TV_MODE_TEST(_name, _supported, _default, false, 0, __VA_ARGS__)
96 :
97 : #define TV_MODE_TEST_CMDLINE(_name, _supported, _default, _cmdline, ...) \
98 : _TV_MODE_TEST(_name, _supported, _default, true, _cmdline, __VA_ARGS__)
99 :
100 : static void
101 7 : drm_test_connector_helper_tv_get_modes_check(struct kunit *test)
102 : {
103 7 : const struct drm_connector_helper_tv_get_modes_test *params = test->param_value;
104 7 : struct drm_probe_helper_test_priv *priv = test->priv;
105 7 : struct drm_connector *connector = &priv->connector;
106 7 : struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
107 : struct drm_display_mode *mode;
108 : const struct drm_display_mode *expected;
109 : size_t len;
110 : int ret;
111 :
112 7 : if (params->cmdline) {
113 2 : cmdline->tv_mode_specified = true;
114 2 : cmdline->tv_mode = params->cmdline_mode;
115 : }
116 :
117 7 : ret = drm_mode_create_tv_properties(priv->drm, params->supported_tv_modes);
118 7 : KUNIT_ASSERT_EQ(test, ret, 0);
119 :
120 14 : drm_object_attach_property(&connector->base,
121 7 : priv->drm->mode_config.tv_mode_property,
122 7 : params->default_mode);
123 :
124 7 : mutex_lock(&priv->drm->mode_config.mutex);
125 :
126 7 : ret = drm_connector_helper_tv_get_modes(connector);
127 7 : KUNIT_EXPECT_EQ(test, ret, params->num_expected_modes);
128 :
129 7 : len = 0;
130 17 : list_for_each_entry(mode, &connector->probed_modes, head)
131 10 : len++;
132 7 : KUNIT_EXPECT_EQ(test, len, params->num_expected_modes);
133 :
134 7 : if (params->num_expected_modes >= 1) {
135 6 : mode = list_first_entry_or_null(&connector->probed_modes,
136 : struct drm_display_mode, head);
137 6 : KUNIT_ASSERT_NOT_NULL(test, mode);
138 :
139 6 : expected = params->expected_modes[0](priv->drm);
140 6 : KUNIT_ASSERT_NOT_NULL(test, expected);
141 :
142 6 : KUNIT_EXPECT_TRUE(test, drm_mode_equal(mode, expected));
143 6 : KUNIT_EXPECT_TRUE(test, mode->type & DRM_MODE_TYPE_PREFERRED);
144 : }
145 :
146 7 : if (params->num_expected_modes >= 2) {
147 4 : mode = list_next_entry(mode, head);
148 4 : KUNIT_ASSERT_NOT_NULL(test, mode);
149 :
150 4 : expected = params->expected_modes[1](priv->drm);
151 4 : KUNIT_ASSERT_NOT_NULL(test, expected);
152 :
153 4 : KUNIT_EXPECT_TRUE(test, drm_mode_equal(mode, expected));
154 4 : KUNIT_EXPECT_FALSE(test, mode->type & DRM_MODE_TYPE_PREFERRED);
155 : }
156 :
157 7 : mutex_unlock(&priv->drm->mode_config.mutex);
158 7 : }
159 :
160 : static const
161 : struct drm_connector_helper_tv_get_modes_test drm_connector_helper_tv_get_modes_tests[] = {
162 : { .name = "None" },
163 : TV_MODE_TEST("PAL",
164 : BIT(DRM_MODE_TV_MODE_PAL),
165 : DRM_MODE_TV_MODE_PAL,
166 : drm_mode_analog_pal_576i),
167 : TV_MODE_TEST("NTSC",
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),
189 : };
190 :
191 : static void
192 7 : drm_connector_helper_tv_get_modes_desc(const struct drm_connector_helper_tv_get_modes_test *t,
193 : char *desc)
194 : {
195 7 : sprintf(desc, "%s", t->name);
196 7 : }
197 :
198 8 : 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);
201 :
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),
205 : { }
206 : };
207 :
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,
213 : };
214 :
215 : kunit_test_suite(drm_test_connector_helper_tv_get_modes_suite);
216 :
217 : MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
218 : MODULE_LICENSE("GPL");
|