xref: /aosp_15_r20/external/igt-gpu-tools/tests/amdgpu/amd_bypass.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
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