1 /*
2  * Copyright 2014 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 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <stdio.h>
29 
30 #include "CUnit/Basic.h"
31 
32 #include "util_math.h"
33 
34 #include "amdgpu_test.h"
35 #include "uvd_messages.h"
36 #include "amdgpu_drm.h"
37 #include "amdgpu_internal.h"
38 
39 #define IB_SIZE		4096
40 #define MAX_RESOURCES	16
41 
42 static amdgpu_device_handle device_handle;
43 static uint32_t major_version;
44 static uint32_t minor_version;
45 static uint32_t family_id;
46 
47 static amdgpu_context_handle context_handle;
48 static amdgpu_bo_handle ib_handle;
49 static uint64_t ib_mc_address;
50 static uint32_t *ib_cpu;
51 static amdgpu_va_handle ib_va_handle;
52 
53 static amdgpu_bo_handle resources[MAX_RESOURCES];
54 static unsigned num_resources;
55 
56 static void amdgpu_cs_uvd_create(void);
57 static void amdgpu_cs_uvd_decode(void);
58 static void amdgpu_cs_uvd_destroy(void);
59 
60 CU_TestInfo cs_tests[] = {
61 	{ "UVD create",  amdgpu_cs_uvd_create },
62 	{ "UVD decode",  amdgpu_cs_uvd_decode },
63 	{ "UVD destroy",  amdgpu_cs_uvd_destroy },
64 	CU_TEST_INFO_NULL,
65 };
66 
suite_cs_tests_init(void)67 int suite_cs_tests_init(void)
68 {
69 	amdgpu_bo_handle ib_result_handle;
70 	void *ib_result_cpu;
71 	uint64_t ib_result_mc_address;
72 	amdgpu_va_handle ib_result_va_handle;
73 	int r;
74 
75 	r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
76 				     &minor_version, &device_handle);
77 	if (r)
78 		return CUE_SINIT_FAILED;
79 
80 	family_id = device_handle->info.family_id;
81 
82 	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
83 	if (r)
84 		return CUE_SINIT_FAILED;
85 
86 	r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096,
87 				    AMDGPU_GEM_DOMAIN_GTT, 0,
88 				    &ib_result_handle, &ib_result_cpu,
89 				    &ib_result_mc_address,
90 				    &ib_result_va_handle);
91 	if (r)
92 		return CUE_SINIT_FAILED;
93 
94 	ib_handle = ib_result_handle;
95 	ib_mc_address = ib_result_mc_address;
96 	ib_cpu = ib_result_cpu;
97 	ib_va_handle = ib_result_va_handle;
98 
99 	return CUE_SUCCESS;
100 }
101 
suite_cs_tests_clean(void)102 int suite_cs_tests_clean(void)
103 {
104 	int r;
105 
106 	r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle,
107 				     ib_mc_address, IB_SIZE);
108 	if (r)
109 		return CUE_SCLEAN_FAILED;
110 
111 	r = amdgpu_cs_ctx_free(context_handle);
112 	if (r)
113 		return CUE_SCLEAN_FAILED;
114 
115 	r = amdgpu_device_deinitialize(device_handle);
116 	if (r)
117 		return CUE_SCLEAN_FAILED;
118 
119 	return CUE_SUCCESS;
120 }
121 
submit(unsigned ndw,unsigned ip)122 static int submit(unsigned ndw, unsigned ip)
123 {
124 	struct amdgpu_cs_request ibs_request = {0};
125 	struct amdgpu_cs_ib_info ib_info = {0};
126 	struct amdgpu_cs_fence fence_status = {0};
127 	uint32_t expired;
128 	int r;
129 
130 	ib_info.ib_mc_address = ib_mc_address;
131 	ib_info.size = ndw;
132 
133 	ibs_request.ip_type = ip;
134 
135 	r = amdgpu_bo_list_create(device_handle, num_resources, resources,
136 				  NULL, &ibs_request.resources);
137 	if (r)
138 		return r;
139 
140 	ibs_request.number_of_ibs = 1;
141 	ibs_request.ibs = &ib_info;
142 	ibs_request.fence_info.handle = NULL;
143 
144 	r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
145 	if (r)
146 		return r;
147 
148 	r = amdgpu_bo_list_destroy(ibs_request.resources);
149 	if (r)
150 		return r;
151 
152 	fence_status.context = context_handle;
153 	fence_status.ip_type = ip;
154 	fence_status.fence = ibs_request.seq_no;
155 
156 	r = amdgpu_cs_query_fence_status(&fence_status,
157 					 AMDGPU_TIMEOUT_INFINITE,
158 					 0, &expired);
159 	if (r)
160 		return r;
161 
162 	return 0;
163 }
164 
uvd_cmd(uint64_t addr,unsigned cmd,int * idx)165 static void uvd_cmd(uint64_t addr, unsigned cmd, int *idx)
166 {
167 	ib_cpu[(*idx)++] = 0x3BC4;
168 	ib_cpu[(*idx)++] = addr;
169 	ib_cpu[(*idx)++] = 0x3BC5;
170 	ib_cpu[(*idx)++] = addr >> 32;
171 	ib_cpu[(*idx)++] = 0x3BC3;
172 	ib_cpu[(*idx)++] = cmd << 1;
173 }
174 
amdgpu_cs_uvd_create(void)175 static void amdgpu_cs_uvd_create(void)
176 {
177 	struct amdgpu_bo_alloc_request req = {0};
178 	amdgpu_bo_handle buf_handle;
179 	uint64_t va = 0;
180 	amdgpu_va_handle va_handle;
181 	void *msg;
182 	int i, r;
183 
184 	req.alloc_size = 4*1024;
185 	req.preferred_heap = AMDGPU_GEM_DOMAIN_GTT;
186 
187 	r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
188 	CU_ASSERT_EQUAL(r, 0);
189 
190 	r = amdgpu_va_range_alloc(device_handle,
191 				  amdgpu_gpu_va_range_general,
192 				  4096, 1, 0, &va,
193 				  &va_handle, 0);
194 	CU_ASSERT_EQUAL(r, 0);
195 
196 	r = amdgpu_bo_va_op(buf_handle, 0, 4096, va, 0, AMDGPU_VA_OP_MAP);
197 	CU_ASSERT_EQUAL(r, 0);
198 
199 	r = amdgpu_bo_cpu_map(buf_handle, &msg);
200 	CU_ASSERT_EQUAL(r, 0);
201 
202 	memcpy(msg, uvd_create_msg, sizeof(uvd_create_msg));
203 	if (family_id >= AMDGPU_FAMILY_VI)
204 		((uint8_t*)msg)[0x10] = 7;
205 
206 	r = amdgpu_bo_cpu_unmap(buf_handle);
207 	CU_ASSERT_EQUAL(r, 0);
208 
209 	num_resources = 0;
210 	resources[num_resources++] = buf_handle;
211 	resources[num_resources++] = ib_handle;
212 
213 	i = 0;
214 	uvd_cmd(va, 0x0, &i);
215 	for (; i % 16; ++i)
216 		ib_cpu[i] = 0x80000000;
217 
218 	r = submit(i, AMDGPU_HW_IP_UVD);
219 	CU_ASSERT_EQUAL(r, 0);
220 
221 	r = amdgpu_bo_va_op(buf_handle, 0, 4096, va, 0, AMDGPU_VA_OP_UNMAP);
222 	CU_ASSERT_EQUAL(r, 0);
223 
224 	r = amdgpu_va_range_free(va_handle);
225 	CU_ASSERT_EQUAL(r, 0);
226 
227 	r = amdgpu_bo_free(buf_handle);
228 	CU_ASSERT_EQUAL(r, 0);
229 }
230 
amdgpu_cs_uvd_decode(void)231 static void amdgpu_cs_uvd_decode(void)
232 {
233 	const unsigned dpb_size = 15923584, dt_size = 737280;
234 	uint64_t msg_addr, fb_addr, bs_addr, dpb_addr, dt_addr, it_addr;
235 	struct amdgpu_bo_alloc_request req = {0};
236 	amdgpu_bo_handle buf_handle;
237 	amdgpu_va_handle va_handle;
238 	uint64_t va = 0;
239 	uint64_t sum;
240 	uint8_t *ptr;
241 	int i, r;
242 
243 	req.alloc_size = 4*1024; /* msg */
244 	req.alloc_size += 4*1024; /* fb */
245 	if (family_id >= AMDGPU_FAMILY_VI)
246 		req.alloc_size += 4096; /*it_scaling_table*/
247 	req.alloc_size += ALIGN(sizeof(uvd_bitstream), 4*1024);
248 	req.alloc_size += ALIGN(dpb_size, 4*1024);
249 	req.alloc_size += ALIGN(dt_size, 4*1024);
250 
251 	req.preferred_heap = AMDGPU_GEM_DOMAIN_GTT;
252 
253 	r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
254 	CU_ASSERT_EQUAL(r, 0);
255 
256 	r = amdgpu_va_range_alloc(device_handle,
257 				  amdgpu_gpu_va_range_general,
258 				  req.alloc_size, 1, 0, &va,
259 				  &va_handle, 0);
260 	CU_ASSERT_EQUAL(r, 0);
261 
262 	r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0,
263 			    AMDGPU_VA_OP_MAP);
264 	CU_ASSERT_EQUAL(r, 0);
265 
266 	r = amdgpu_bo_cpu_map(buf_handle, (void **)&ptr);
267 	CU_ASSERT_EQUAL(r, 0);
268 
269 	memcpy(ptr, uvd_decode_msg, sizeof(uvd_decode_msg));
270 	if (family_id >= AMDGPU_FAMILY_VI)
271 		ptr[0x10] = 7;
272 
273 	ptr += 4*1024;
274 	memset(ptr, 0, 4*1024);
275 	if (family_id >= AMDGPU_FAMILY_VI) {
276 		ptr += 4*1024;
277 		memcpy(ptr, uvd_it_scaling_table, sizeof(uvd_it_scaling_table));
278 	}
279 
280 	ptr += 4*1024;
281 	memcpy(ptr, uvd_bitstream, sizeof(uvd_bitstream));
282 
283 	ptr += ALIGN(sizeof(uvd_bitstream), 4*1024);
284 	memset(ptr, 0, dpb_size);
285 
286 	ptr += ALIGN(dpb_size, 4*1024);
287 	memset(ptr, 0, dt_size);
288 
289 	num_resources = 0;
290 	resources[num_resources++] = buf_handle;
291 	resources[num_resources++] = ib_handle;
292 
293 	msg_addr = va;
294 	fb_addr = msg_addr + 4*1024;
295 	if (family_id >= AMDGPU_FAMILY_VI) {
296 		it_addr = fb_addr + 4*1024;
297 		bs_addr = it_addr + 4*1024;
298 	} else
299 		bs_addr = fb_addr + 4*1024;
300 	dpb_addr = ALIGN(bs_addr + sizeof(uvd_bitstream), 4*1024);
301 	dt_addr = ALIGN(dpb_addr + dpb_size, 4*1024);
302 
303 	i = 0;
304 	uvd_cmd(msg_addr, 0x0, &i);
305 	uvd_cmd(dpb_addr, 0x1, &i);
306 	uvd_cmd(dt_addr, 0x2, &i);
307 	uvd_cmd(fb_addr, 0x3, &i);
308 	uvd_cmd(bs_addr, 0x100, &i);
309 	if (family_id >= AMDGPU_FAMILY_VI)
310 		uvd_cmd(it_addr, 0x204, &i);
311 	ib_cpu[i++] = 0x3BC6;
312 	ib_cpu[i++] = 0x1;
313 	for (; i % 16; ++i)
314 		ib_cpu[i] = 0x80000000;
315 
316 	r = submit(i, AMDGPU_HW_IP_UVD);
317 	CU_ASSERT_EQUAL(r, 0);
318 
319 	/* TODO: use a real CRC32 */
320 	for (i = 0, sum = 0; i < dt_size; ++i)
321 		sum += ptr[i];
322 	CU_ASSERT_EQUAL(sum, 0x20345d8);
323 
324 	r = amdgpu_bo_cpu_unmap(buf_handle);
325 	CU_ASSERT_EQUAL(r, 0);
326 
327 	r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0, AMDGPU_VA_OP_UNMAP);
328 	CU_ASSERT_EQUAL(r, 0);
329 
330 	r = amdgpu_va_range_free(va_handle);
331 	CU_ASSERT_EQUAL(r, 0);
332 
333 	r = amdgpu_bo_free(buf_handle);
334 	CU_ASSERT_EQUAL(r, 0);
335 }
336 
amdgpu_cs_uvd_destroy(void)337 static void amdgpu_cs_uvd_destroy(void)
338 {
339 	struct amdgpu_bo_alloc_request req = {0};
340 	amdgpu_bo_handle buf_handle;
341 	amdgpu_va_handle va_handle;
342 	uint64_t va = 0;
343 	void *msg;
344 	int i, r;
345 
346 	req.alloc_size = 4*1024;
347 	req.preferred_heap = AMDGPU_GEM_DOMAIN_GTT;
348 
349 	r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
350 	CU_ASSERT_EQUAL(r, 0);
351 
352 	r = amdgpu_va_range_alloc(device_handle,
353 				  amdgpu_gpu_va_range_general,
354 				  req.alloc_size, 1, 0, &va,
355 				  &va_handle, 0);
356 	CU_ASSERT_EQUAL(r, 0);
357 
358 	r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0,
359 			    AMDGPU_VA_OP_MAP);
360 	CU_ASSERT_EQUAL(r, 0);
361 
362 	r = amdgpu_bo_cpu_map(buf_handle, &msg);
363 	CU_ASSERT_EQUAL(r, 0);
364 
365 	memcpy(msg, uvd_destroy_msg, sizeof(uvd_destroy_msg));
366 	if (family_id >= AMDGPU_FAMILY_VI)
367 		((uint8_t*)msg)[0x10] = 7;
368 
369 	r = amdgpu_bo_cpu_unmap(buf_handle);
370 	CU_ASSERT_EQUAL(r, 0);
371 
372 	num_resources = 0;
373 	resources[num_resources++] = buf_handle;
374 	resources[num_resources++] = ib_handle;
375 
376 	i = 0;
377 	uvd_cmd(va, 0x0, &i);
378 	for (; i % 16; ++i)
379 		ib_cpu[i] = 0x80000000;
380 
381 	r = submit(i, AMDGPU_HW_IP_UVD);
382 	CU_ASSERT_EQUAL(r, 0);
383 
384 	r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0, AMDGPU_VA_OP_UNMAP);
385 	CU_ASSERT_EQUAL(r, 0);
386 
387 	r = amdgpu_va_range_free(va_handle);
388 	CU_ASSERT_EQUAL(r, 0);
389 
390 	r = amdgpu_bo_free(buf_handle);
391 	CU_ASSERT_EQUAL(r, 0);
392 }
393