1 /*
2 * Copyright 2019 Advanced Micro Devices, Inc.
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 shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 */
23 #include "igt.h"
24
25 /*
26 * internal use
27 * Common test data
28 * */
29 typedef struct {
30 int drm_fd;
31 int width;
32 int height;
33 enum pipe pipe_id;
34 igt_display_t display;
35 igt_plane_t *primary;
36 igt_output_t *output;
37 igt_pipe_t *pipe;
38 igt_pipe_crc_t *pipe_crc;
39 igt_crc_t crc_fb;
40 igt_crc_t crc_dprx;
41 drmModeModeInfo *mode;
42 } data_t;
43
44 enum pattern {
45 TEST_PATTERN_DP_COLOR_RAMP,
46 TEST_PATTERN_DP_BLACK_WHITE_VERT_LINES,
47 TEST_PATTERN_DP_BLACK_WHITE_HORZ_LINES,
48 TEST_PATTERN_DP_COLOR_SQUARES_VESA,
49 /* please don't add pattern after the below line */
50 TEST_PATTERN_MAX,
51 };
52
53 const char *ptnstr[TEST_PATTERN_MAX] = {
54 "DP Color Ramp",
55 "DP Vertical Lines",
56 "DP Horizontal Lines",
57 "DP Color Squares VESA"
58 };
59
60 /* Common test setup. */
test_init(data_t * data)61 static void test_init(data_t *data)
62 {
63 igt_display_t *display = &data->display;
64
65 /* It doesn't matter which pipe we choose on amdpgu. */
66 data->pipe_id = PIPE_A;
67 data->pipe = &data->display.pipes[data->pipe_id];
68
69 igt_display_reset(display);
70
71 data->output = igt_get_single_output_for_pipe(display, data->pipe_id);
72 igt_assert(data->output);
73
74 data->mode = igt_output_get_mode(data->output);
75 igt_assert(data->mode);
76
77 data->primary =
78 igt_pipe_get_plane_type(data->pipe, DRM_PLANE_TYPE_PRIMARY);
79
80 data->pipe_crc = igt_pipe_crc_new(data->drm_fd, data->pipe_id,
81 AMDGPU_PIPE_CRC_SOURCE_DPRX);
82
83 igt_output_set_pipe(data->output, data->pipe_id);
84
85 data->width = data->mode->hdisplay;
86 data->height = data->mode->vdisplay;
87 }
88
89 /* Common test cleanup. */
test_fini(data_t * data)90 static void test_fini(data_t *data)
91 {
92 igt_pipe_crc_free(data->pipe_crc);
93 igt_display_reset(&data->display);
94 }
95
96 /*
97 * draw the DP color ramp test pattern
98 * Reference: DP Link CTS 1.2 Core r1.1, sec. 3.1.5.1
99 */
draw_dp_test_pattern_color_ramp(igt_fb_t * fb)100 static void draw_dp_test_pattern_color_ramp(igt_fb_t *fb)
101 {
102 const int h = 64; /* test pattern rectangle height */
103 const int block_h = h * 4; /* block height of R-G-B-White rectangles */
104 void *ptr_fb;
105 uint8_t *data;
106 int x,y;
107 int i;
108 uint8_t val;
109
110 /*
111 * 64-by-256 pixels per rectangle
112 * R-G-B-White rectangle in order in vertical
113 * duplicate in horizontal
114 */
115 ptr_fb = igt_fb_map_buffer(fb->fd, fb);
116 igt_assert(ptr_fb);
117 data = ptr_fb + fb->offsets[0];
118
119 switch (fb->drm_format) {
120 case DRM_FORMAT_XRGB8888:
121 for (y = 0; y < fb->height; ++y) {
122 for (x = 0, val = 0; x < fb->width; ++x, ++val) {
123 i = x * 4 + y * fb->strides[0];
124
125 /* vertical R-G-B-White rect */
126 if ((y % block_h) < h) { /* Red */
127 data[i + 2] = val;
128 data[i + 1] = 0;
129 data[i + 0] = 0;
130 } else if ((y % block_h) < 2 * h) { /* Green */
131 data[i + 2] = 0;
132 data[i + 1] = val;
133 data[i + 0] = 0;
134 } else if ((y % block_h) < 3 * h) { /* Blue */
135 data[i + 2] = 0;
136 data[i + 1] = 0;
137 data[i + 0] = val;
138 } else { /* White */
139 data[i + 2] = val;
140 data[i + 1] = val;
141 data[i + 0] = val;
142 }
143 }
144 }
145 break;
146 default:
147 igt_assert_f(0, "DRM Format Invalid");
148 break;
149 }
150
151 igt_fb_unmap_buffer(fb, ptr_fb);
152 }
153
154 /*
155 * draw the DP vertical lines test pattern
156 * Reference: DP Link CTS 1.2 Core r1.1, sec. 3.1.5.2
157 */
draw_dp_test_pattern_vert_lines(igt_fb_t * fb)158 static void draw_dp_test_pattern_vert_lines(igt_fb_t *fb)
159 {
160 void *ptr_fb;
161 uint8_t *data;
162 int x, y;
163 int i;
164
165 /* alternating black and white lines, 1 pixel wide */
166 ptr_fb = igt_fb_map_buffer(fb->fd, fb);
167 igt_assert(ptr_fb);
168 data = ptr_fb + fb->offsets[0];
169
170 switch (fb->drm_format) {
171 case DRM_FORMAT_XRGB8888:
172 for (y = 0; y < fb->height; ++y) {
173 for (x = 0; x < fb->width; ++x) {
174 i = x * 4 + y * fb->strides[0];
175
176 if ((x & 1) == 0) {
177 data[i + 2] = 0xff; /* R */
178 data[i + 1] = 0xff; /* G */
179 data[i + 0] = 0xff; /* B */
180 } else {
181 data[i + 2] = 0;
182 data[i + 1] = 0;
183 data[i + 0] = 0;
184 }
185 }
186 }
187 break;
188 default:
189 igt_assert_f(0, "DRM Format Invalid");
190 break;
191 }
192
193 igt_fb_unmap_buffer(fb, ptr_fb);
194 }
195
196 /* draw the DP horizontal lines test pattern */
draw_dp_test_pattern_horz_lines(igt_fb_t * fb)197 static void draw_dp_test_pattern_horz_lines(igt_fb_t *fb)
198 {
199 void *ptr_fb;
200 uint8_t *data;
201 int x, y;
202 int i;
203
204 /* alternating black and white horizontal lines, 1 pixel high */
205 ptr_fb = igt_fb_map_buffer(fb->fd, fb);
206 igt_assert(ptr_fb);
207 data = ptr_fb + fb->offsets[0];
208
209 switch (fb->drm_format) {
210 case DRM_FORMAT_XRGB8888:
211 for (y = 0; y < fb->height; ++y) {
212 for (x = 0; x < fb->width; ++x) {
213
214 i = x * 4 + y * fb->strides[0];
215
216 if ((y & 1) == 0) {
217 data[i + 2] = 0xff; /* R */
218 data[i + 1] = 0xff; /* G */
219 data[i + 0] = 0xff; /* B */
220 } else {
221 data[i + 2] = 0;
222 data[i + 1] = 0;
223 data[i + 0] = 0;
224 }
225 }
226 }
227 break;
228 default:
229 igt_assert_f(0, "DRM Format Invalid");
230 break;
231 }
232
233 igt_fb_unmap_buffer(fb, ptr_fb);
234 }
235
236 /*
237 * draw the DP color squares VESA test pattern
238 * Reference: DP Link CTS 1.2 Core r1.1, sec. 3.1.5.3
239 */
draw_dp_test_pattern_color_squares_vesa(igt_fb_t * fb)240 static void draw_dp_test_pattern_color_squares_vesa(igt_fb_t *fb)
241 {
242 const int h = 64; /* test pattern square height/width */
243 const int block_h = h * 2; /* block height of the repetition pattern */
244 const int block_w = h * 8; /* block width of the repetition pattern */
245 const uint8_t rgb[3][2][8] = {
246 {/* Red table of the pattern squares */
247 {255, 255, 0, 0, 255, 255, 0, 0},
248 {0, 255, 255, 0, 0, 255, 255, 0},
249 },
250 {/* Green table */
251 {255, 255, 255, 255, 0, 0, 0, 0},
252 {0, 0, 0, 255, 255, 255, 255, 0},
253 },
254 {/* Blue table */
255 {255, 0, 255, 0, 255, 0, 255, 0},
256 {255, 0, 255, 0, 255, 0, 255, 0},
257 },
258 };
259
260 void *ptr_fb;
261 uint8_t *data;
262 int x, y;
263 int i, j, k;
264
265 ptr_fb = igt_fb_map_buffer(fb->fd, fb);
266 igt_assert(ptr_fb);
267 data = ptr_fb + fb->offsets[0];
268
269 switch (fb->drm_format) {
270 case DRM_FORMAT_XRGB8888:
271 for (y = 0; y < fb->height; ++y) {
272 for (x = 0; x < fb->width; ++x) {
273
274 i = x * 4 + y * fb->strides[0];
275 j = (y % block_h) / h;
276 k = (x % block_w) / h;
277
278 data[i + 2] = rgb[0][j][k]; /* R */
279 data[i + 1] = rgb[1][j][k]; /* G */
280 data[i + 0] = rgb[2][j][k]; /* B */
281 }
282 }
283 break;
284
285 default:
286 igt_assert_f(0, "DRM Format Invalid");
287 break;
288 }
289
290
291 igt_fb_unmap_buffer(fb, ptr_fb);
292 }
293
294 /* generate test pattern and fills a FB */
generate_test_pattern(igt_fb_t * fb,data_t * data,enum pattern ptn)295 static void generate_test_pattern(igt_fb_t *fb, data_t *data, enum pattern ptn)
296 {
297 igt_assert(fb->fd && (ptn < TEST_PATTERN_MAX));
298
299 if (ptn == TEST_PATTERN_DP_COLOR_RAMP) {
300 draw_dp_test_pattern_color_ramp(fb);
301 } else if (ptn == TEST_PATTERN_DP_BLACK_WHITE_VERT_LINES) {
302 draw_dp_test_pattern_vert_lines(fb);
303 } else if (ptn == TEST_PATTERN_DP_BLACK_WHITE_HORZ_LINES) {
304 draw_dp_test_pattern_horz_lines(fb);
305 } else if (ptn == TEST_PATTERN_DP_COLOR_SQUARES_VESA) {
306 draw_dp_test_pattern_color_squares_vesa(fb);
307 }
308 }
309
bypass_8bpc_test(data_t * data)310 static void bypass_8bpc_test(data_t *data)
311 {
312 igt_display_t *display = &data->display;
313 igt_fb_t fb;
314 enum pattern ptn;
315
316 test_init(data);
317
318 igt_create_fb(data->drm_fd, data->width, data->height,
319 DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE, &fb);
320
321 /*
322 * Settings:
323 * no degamma
324 * no regamma
325 * no CTM
326 */
327 igt_pipe_obj_replace_prop_blob(data->pipe, IGT_CRTC_DEGAMMA_LUT, NULL, 0);
328 igt_pipe_obj_replace_prop_blob(data->pipe, IGT_CRTC_GAMMA_LUT, NULL, 0);
329 igt_pipe_obj_replace_prop_blob(data->pipe, IGT_CRTC_CTM, NULL, 0);
330
331 igt_plane_set_fb(data->primary, &fb);
332 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
333
334 /* traverse all the test pattern to validate 8bpc bypass mode */
335 for (ptn = TEST_PATTERN_DP_COLOR_RAMP; ptn < TEST_PATTERN_MAX; ++ptn) {
336 igt_info("Test Pattern: %s\n", ptnstr[ptn]);
337
338 generate_test_pattern(&fb, data, ptn);
339
340 /* Grab FB and DPRX CRCs and compare */
341 igt_fb_calc_crc(&fb, &data->crc_fb);
342 igt_pipe_crc_collect_crc(data->pipe_crc, &data->crc_dprx);
343
344 igt_assert_crc_equal(&data->crc_fb, &data->crc_dprx);
345 }
346
347 igt_plane_set_fb(data->primary, NULL);
348 test_fini(data);
349 igt_remove_fb(data->drm_fd, &fb);
350 }
351
352 igt_main
353 {
354 data_t data;
355 memset(&data, 0, sizeof(data));
356
357 igt_skip_on_simulation();
358
359 igt_fixture {
360 data.drm_fd = drm_open_driver_master(DRIVER_AMDGPU);
361 if (data.drm_fd == -1)
362 igt_skip("Not an amdgpu driver.\n");
363 igt_require_pipe_crc(data.drm_fd);
364
365 kmstest_set_vt_graphics_mode();
366
367 igt_display_require(&data.display, data.drm_fd);
368 igt_require(data.display.is_atomic);
369 igt_display_require_output(&data.display);
370 }
371
372 igt_subtest("8bpc-bypass-mode")
373 bypass_8bpc_test(&data);
374
375 igt_fixture {
376 igt_display_fini(&data.display);
377 }
378 }
379