1 /*
2 * Copyright © 2014 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 */
24
25 #include "igt.h"
26
27 IGT_TEST_DESCRIPTION("Check the debugfs force connector/edid features work"
28 " correctly.");
29
30 #define CHECK_MODE(m, h, w, r) \
31 igt_assert_eq(m.hdisplay, h); igt_assert_eq(m.vdisplay, w); \
32 igt_assert_eq(m.vrefresh, r);
33
reset_connectors(void)34 static void reset_connectors(void)
35 {
36 int drm_fd = 0;
37 drmModeRes *res;
38 drmModeConnector *connector = NULL;
39
40 drm_fd = drm_open_driver_master(DRIVER_INTEL);
41 res = drmModeGetResources(drm_fd);
42
43 for (int i = 0; i < res->count_connectors; i++) {
44
45 connector = drmModeGetConnectorCurrent(drm_fd,
46 res->connectors[i]);
47
48 kmstest_force_connector(drm_fd, connector,
49 FORCE_CONNECTOR_UNSPECIFIED);
50
51 kmstest_force_edid(drm_fd, connector, NULL);
52
53 drmModeFreeConnector(connector);
54 }
55
56 igt_set_module_param_int("load_detect_test", 0);
57 }
58
opt_handler(int opt,int opt_index,void * data)59 static int opt_handler(int opt, int opt_index, void *data)
60 {
61 switch (opt) {
62 case 'r':
63 reset_connectors();
64 exit(0);
65 break;
66 }
67
68 return IGT_OPT_HANDLER_SUCCESS;
69 }
70
71 struct option long_opts[] = {
72 {"reset", 0, 0, 'r'},
73 {0, 0, 0, 0}
74 };
75 const char *help_str =
76 " --reset\t\tReset all connector force states and edid.\n";
77
78 igt_main_args("", long_opts, help_str, opt_handler, NULL)
79 {
80 /* force the VGA output and test that it worked */
81 int drm_fd = 0;
82 drmModeRes *res;
83 drmModeConnector *vga_connector = NULL, *temp;
84 int start_n_modes, start_connection;
85
86 igt_fixture {
87 unsigned vga_connector_id = 0;
88
89 drm_fd = drm_open_driver_master(DRIVER_INTEL);
90
91 res = drmModeGetResources(drm_fd);
92 igt_require(res);
93
94 /* find the vga connector */
95 for (int i = 0; i < res->count_connectors; i++) {
96 vga_connector = drmModeGetConnectorCurrent(drm_fd,
97 res->connectors[i]);
98
99 if (vga_connector->connector_type == DRM_MODE_CONNECTOR_VGA) {
100 /* Ensure that no override was left in place. */
101 kmstest_force_connector(drm_fd,
102 vga_connector,
103 FORCE_CONNECTOR_UNSPECIFIED);
104
105 /* Only use the first VGA connector. */
106 if (!vga_connector_id)
107 vga_connector_id = res->connectors[i];
108 }
109
110 drmModeFreeConnector(vga_connector);
111 }
112
113 igt_require(vga_connector_id);
114
115 /* Reacquire status after clearing any previous overrides */
116 vga_connector = drmModeGetConnector(drm_fd, vga_connector_id);
117
118 start_n_modes = vga_connector->count_modes;
119 start_connection = vga_connector->connection;
120 }
121
122 igt_subtest("force-load-detect") {
123 int i, j, w = 64, h = 64;
124 drmModePlaneRes *plane_resources;
125 struct igt_fb xrgb_fb, argb_fb;
126
127 igt_create_fb(drm_fd, w, h, DRM_FORMAT_XRGB8888, 0, &xrgb_fb);
128 igt_create_fb(drm_fd, w, h, DRM_FORMAT_ARGB8888, 0, &argb_fb);
129 igt_assert(drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) == 0);
130
131 /*
132 * disable all outputs to make sure we have a
133 * free crtc available for load detect
134 */
135 kmstest_set_vt_graphics_mode();
136 kmstest_unset_all_crtcs(drm_fd, res);
137
138 igt_set_module_param_int("load_detect_test", 1);
139
140 plane_resources = drmModeGetPlaneResources(drm_fd);
141 igt_assert(plane_resources);
142
143 for (i = 0; i < plane_resources->count_planes; i++) {
144 drmModePlane *drm_plane;
145 bool found = false;
146 uint32_t plane_id = plane_resources->planes[i];
147
148 drm_plane = drmModeGetPlane(drm_fd, plane_id);
149 igt_assert(drm_plane);
150
151 for (j = 0; j < drm_plane->count_formats; j++) {
152 uint32_t format = drm_plane->formats[j];
153 uint32_t crtc = ffs(drm_plane->possible_crtcs) - 1;
154 uint32_t crtc_id = res->crtcs[crtc];
155
156 if (format == DRM_FORMAT_XRGB8888)
157 do_or_die(drmModeSetPlane(drm_fd, plane_id, crtc_id,
158 xrgb_fb.fb_id,
159 0, 0, 0, w, h,
160 0, 0, IGT_FIXED(w, 0), IGT_FIXED(h, 0)));
161 else if (format == DRM_FORMAT_ARGB8888)
162 do_or_die(drmModeSetPlane(drm_fd, plane_id, crtc_id,
163 argb_fb.fb_id,
164 0, 0, 0, w, h,
165 0, 0, IGT_FIXED(w, 0), IGT_FIXED(h, 0)));
166 else
167 continue;
168
169 found = true;
170 break;
171 }
172 drmModeFreePlane(drm_plane);
173 igt_assert(found);
174 }
175
176 /* This can't use drmModeGetConnectorCurrent
177 * because connector probing is the point of this test.
178 */
179 temp = drmModeGetConnector(drm_fd, vga_connector->connector_id);
180
181 igt_set_module_param_int("load_detect_test", 0);
182
183 igt_assert(temp->connection != DRM_MODE_UNKNOWNCONNECTION);
184
185 drmModeFreeConnector(temp);
186
187 /* Look if planes are unmodified. */
188 for (i = 0; i < plane_resources->count_planes; i++) {
189 drmModePlane *drm_plane;
190
191 drm_plane = drmModeGetPlane(drm_fd,
192 plane_resources->planes[i]);
193 igt_assert(drm_plane);
194
195 igt_assert(drm_plane->crtc_id);
196 igt_assert(drm_plane->fb_id);
197
198 if (drm_plane->fb_id != xrgb_fb.fb_id)
199 igt_assert_eq(drm_plane->fb_id, argb_fb.fb_id);
200
201 drmModeFreePlane(drm_plane);
202 }
203 }
204
205 igt_subtest("force-connector-state") {
206 igt_display_t display;
207
208 /* force the connector on and check the reported values */
209 kmstest_force_connector(drm_fd, vga_connector, FORCE_CONNECTOR_ON);
210 temp = drmModeGetConnectorCurrent(drm_fd,
211 vga_connector->connector_id);
212 igt_assert_eq(temp->connection, DRM_MODE_CONNECTED);
213 igt_assert_lt(0, temp->count_modes);
214 drmModeFreeConnector(temp);
215
216 /* attempt to use the display */
217 kmstest_set_vt_graphics_mode();
218 igt_display_require(&display, drm_fd);
219 igt_display_commit(&display);
220 igt_display_fini(&display);
221
222
223 /* force the connector off */
224 kmstest_force_connector(drm_fd, vga_connector,
225 FORCE_CONNECTOR_OFF);
226 temp = drmModeGetConnectorCurrent(drm_fd,
227 vga_connector->connector_id);
228 igt_assert_eq(temp->connection, DRM_MODE_DISCONNECTED);
229 igt_assert_eq(0, temp->count_modes);
230 drmModeFreeConnector(temp);
231
232 /* check that the previous state is restored */
233 kmstest_force_connector(drm_fd, vga_connector,
234 FORCE_CONNECTOR_UNSPECIFIED);
235 temp = drmModeGetConnectorCurrent(drm_fd,
236 vga_connector->connector_id);
237 igt_assert_eq(temp->connection, start_connection);
238 drmModeFreeConnector(temp);
239 }
240
241 igt_subtest("force-edid") {
242 kmstest_force_connector(drm_fd, vga_connector,
243 FORCE_CONNECTOR_ON);
244 temp = drmModeGetConnectorCurrent(drm_fd,
245 vga_connector->connector_id);
246 drmModeFreeConnector(temp);
247
248 /* test edid forcing */
249 kmstest_force_edid(drm_fd, vga_connector,
250 igt_kms_get_base_edid());
251 temp = drmModeGetConnectorCurrent(drm_fd,
252 vga_connector->connector_id);
253
254 igt_debug("num_conn %i\n", temp->count_modes);
255
256 CHECK_MODE(temp->modes[0], 1920, 1080, 60);
257 /* Don't check non-preferred modes to avoid to tight coupling
258 * with the in-kernel EDID parser. */
259
260 drmModeFreeConnector(temp);
261
262 /* remove edid */
263 kmstest_force_edid(drm_fd, vga_connector, NULL);
264 kmstest_force_connector(drm_fd, vga_connector,
265 FORCE_CONNECTOR_UNSPECIFIED);
266 temp = drmModeGetConnectorCurrent(drm_fd,
267 vga_connector->connector_id);
268 /* the connector should now have the same number of modes that
269 * it started with */
270 igt_assert_eq(temp->count_modes, start_n_modes);
271 drmModeFreeConnector(temp);
272
273 }
274
275 igt_subtest("prune-stale-modes") {
276 int i;
277
278 kmstest_force_connector(drm_fd, vga_connector,
279 FORCE_CONNECTOR_ON);
280
281 /* test pruning of stale modes */
282 kmstest_force_edid(drm_fd, vga_connector,
283 igt_kms_get_alt_edid());
284 temp = drmModeGetConnectorCurrent(drm_fd,
285 vga_connector->connector_id);
286
287 for (i = 0; i < temp->count_modes; i++) {
288 if (temp->modes[i].hdisplay == 1400 &&
289 temp->modes[i].vdisplay == 1050)
290 break;
291 }
292 igt_assert_f(i != temp->count_modes, "1400x1050 not on mode list\n");
293
294 drmModeFreeConnector(temp);
295
296 kmstest_force_edid(drm_fd, vga_connector,
297 igt_kms_get_base_edid());
298 temp = drmModeGetConnectorCurrent(drm_fd,
299 vga_connector->connector_id);
300
301 for (i = 0; i < temp->count_modes; i++) {
302 if (temp->modes[i].hdisplay == 1400 &&
303 temp->modes[i].vdisplay == 1050)
304 break;
305 }
306 igt_assert_f(i == temp->count_modes, "1400x1050 not pruned from mode list\n");
307
308 drmModeFreeConnector(temp);
309
310 kmstest_force_edid(drm_fd, vga_connector, NULL);
311 kmstest_force_connector(drm_fd, vga_connector,
312 FORCE_CONNECTOR_UNSPECIFIED);
313 }
314
315 igt_fixture {
316 drmModeFreeConnector(vga_connector);
317 close(drm_fd);
318
319 reset_connectors();
320 }
321 }
322