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