xref: /third_party/libdrm/tests/amdgpu/vcn_tests.c (revision d722e3fb)
1/*
2 * Copyright 2017 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#include <stdio.h>
25#include <inttypes.h>
26
27#include "CUnit/Basic.h"
28
29#include "util_math.h"
30
31#include "amdgpu_test.h"
32#include "amdgpu_drm.h"
33#include "amdgpu_internal.h"
34#include "decode_messages.h"
35
36#define IB_SIZE		4096
37#define MAX_RESOURCES	16
38
39struct amdgpu_vcn_bo {
40	amdgpu_bo_handle handle;
41	amdgpu_va_handle va_handle;
42	uint64_t addr;
43	uint64_t size;
44	uint8_t *ptr;
45};
46
47struct amdgpu_vcn_reg {
48	uint32_t data0;
49	uint32_t data1;
50	uint32_t cmd;
51	uint32_t nop;
52	uint32_t cntl;
53};
54
55static amdgpu_device_handle device_handle;
56static uint32_t major_version;
57static uint32_t minor_version;
58static uint32_t family_id;
59static uint32_t chip_rev;
60static uint32_t chip_id;
61static uint32_t asic_id;
62static uint32_t chip_rev;
63static uint32_t chip_id;
64
65static amdgpu_context_handle context_handle;
66static amdgpu_bo_handle ib_handle;
67static amdgpu_va_handle ib_va_handle;
68static uint64_t ib_mc_address;
69static uint32_t *ib_cpu;
70
71static amdgpu_bo_handle resources[MAX_RESOURCES];
72static unsigned num_resources;
73
74static uint8_t vcn_reg_index;
75static struct amdgpu_vcn_reg reg[] = {
76	{0x81c4, 0x81c5, 0x81c3, 0x81ff, 0x81c6},
77	{0x504, 0x505, 0x503, 0x53f, 0x506},
78	{0x10, 0x11, 0xf, 0x29, 0x26d},
79};
80
81static void amdgpu_cs_vcn_dec_create(void);
82static void amdgpu_cs_vcn_dec_decode(void);
83static void amdgpu_cs_vcn_dec_destroy(void);
84
85static void amdgpu_cs_vcn_enc_create(void);
86static void amdgpu_cs_vcn_enc_encode(void);
87static void amdgpu_cs_vcn_enc_destroy(void);
88
89CU_TestInfo vcn_tests[] = {
90
91	{ "VCN DEC create",  amdgpu_cs_vcn_dec_create },
92	{ "VCN DEC decode",  amdgpu_cs_vcn_dec_decode },
93	{ "VCN DEC destroy",  amdgpu_cs_vcn_dec_destroy },
94
95	{ "VCN ENC create",  amdgpu_cs_vcn_enc_create },
96	{ "VCN ENC decode",  amdgpu_cs_vcn_enc_encode },
97	{ "VCN ENC destroy",  amdgpu_cs_vcn_enc_destroy },
98	CU_TEST_INFO_NULL,
99};
100
101CU_BOOL suite_vcn_tests_enable(void)
102{
103	struct drm_amdgpu_info_hw_ip info;
104	int r;
105
106	if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
107				   &minor_version, &device_handle))
108		return CU_FALSE;
109
110	family_id = device_handle->info.family_id;
111	asic_id = device_handle->info.asic_id;
112	chip_rev = device_handle->info.chip_rev;
113	chip_id = device_handle->info.chip_external_rev;
114
115	r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_VCN_DEC, 0, &info);
116
117	if (amdgpu_device_deinitialize(device_handle))
118			return CU_FALSE;
119
120	if (r != 0 || !info.available_rings ||
121	    (family_id < AMDGPU_FAMILY_RV &&
122	     (family_id == AMDGPU_FAMILY_AI &&
123	      (chip_id - chip_rev) < 0x32))) {  /* Arcturus */
124		printf("\n\nThe ASIC NOT support VCN, suite disabled\n");
125		return CU_FALSE;
126	}
127
128	if (family_id == AMDGPU_FAMILY_AI) {
129		amdgpu_set_test_active("VCN Tests", "VCN ENC create", CU_FALSE);
130		amdgpu_set_test_active("VCN Tests", "VCN ENC decode", CU_FALSE);
131		amdgpu_set_test_active("VCN Tests", "VCN ENC destroy", CU_FALSE);
132	}
133
134	if (info.hw_ip_version_major == 1)
135		vcn_reg_index = 0;
136	else if (info.hw_ip_version_major == 2)
137		vcn_reg_index = 1;
138	else if ((info.hw_ip_version_major == 2 && info.hw_ip_version_minor >= 5) ||
139		  info.hw_ip_version_major == 3)
140		vcn_reg_index = 2;
141	else
142		return CU_FALSE;
143
144	return CU_TRUE;
145}
146
147int suite_vcn_tests_init(void)
148{
149	int r;
150
151	r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
152				     &minor_version, &device_handle);
153	if (r)
154		return CUE_SINIT_FAILED;
155
156	family_id = device_handle->info.family_id;
157
158	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
159	if (r)
160		return CUE_SINIT_FAILED;
161
162	r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096,
163				    AMDGPU_GEM_DOMAIN_GTT, 0,
164				    &ib_handle, (void**)&ib_cpu,
165				    &ib_mc_address, &ib_va_handle);
166	if (r)
167		return CUE_SINIT_FAILED;
168
169	return CUE_SUCCESS;
170}
171
172int suite_vcn_tests_clean(void)
173{
174	int r;
175
176	r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle,
177			     ib_mc_address, IB_SIZE);
178	if (r)
179		return CUE_SCLEAN_FAILED;
180
181	r = amdgpu_cs_ctx_free(context_handle);
182	if (r)
183		return CUE_SCLEAN_FAILED;
184
185	r = amdgpu_device_deinitialize(device_handle);
186	if (r)
187		return CUE_SCLEAN_FAILED;
188
189	return CUE_SUCCESS;
190}
191
192static int submit(unsigned ndw, unsigned ip)
193{
194	struct amdgpu_cs_request ibs_request = {0};
195	struct amdgpu_cs_ib_info ib_info = {0};
196	struct amdgpu_cs_fence fence_status = {0};
197	uint32_t expired;
198	int r;
199
200	ib_info.ib_mc_address = ib_mc_address;
201	ib_info.size = ndw;
202
203	ibs_request.ip_type = ip;
204
205	r = amdgpu_bo_list_create(device_handle, num_resources, resources,
206				  NULL, &ibs_request.resources);
207	if (r)
208		return r;
209
210	ibs_request.number_of_ibs = 1;
211	ibs_request.ibs = &ib_info;
212	ibs_request.fence_info.handle = NULL;
213
214	r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
215	if (r)
216		return r;
217
218	r = amdgpu_bo_list_destroy(ibs_request.resources);
219	if (r)
220		return r;
221
222	fence_status.context = context_handle;
223	fence_status.ip_type = ip;
224	fence_status.fence = ibs_request.seq_no;
225
226	r = amdgpu_cs_query_fence_status(&fence_status,
227					 AMDGPU_TIMEOUT_INFINITE,
228					 0, &expired);
229	if (r)
230		return r;
231
232	return 0;
233}
234
235static void alloc_resource(struct amdgpu_vcn_bo *vcn_bo,
236			unsigned size, unsigned domain)
237{
238	struct amdgpu_bo_alloc_request req = {0};
239	amdgpu_bo_handle buf_handle;
240	amdgpu_va_handle va_handle;
241	uint64_t va = 0;
242	int r;
243
244	req.alloc_size = ALIGN(size, 4096);
245	req.preferred_heap = domain;
246	r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
247	CU_ASSERT_EQUAL(r, 0);
248	r = amdgpu_va_range_alloc(device_handle,
249				  amdgpu_gpu_va_range_general,
250				  req.alloc_size, 1, 0, &va,
251				  &va_handle, 0);
252	CU_ASSERT_EQUAL(r, 0);
253	r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0,
254			    AMDGPU_VA_OP_MAP);
255	CU_ASSERT_EQUAL(r, 0);
256	vcn_bo->addr = va;
257	vcn_bo->handle = buf_handle;
258	vcn_bo->size = req.alloc_size;
259	vcn_bo->va_handle = va_handle;
260	r = amdgpu_bo_cpu_map(vcn_bo->handle, (void **)&vcn_bo->ptr);
261	CU_ASSERT_EQUAL(r, 0);
262	memset(vcn_bo->ptr, 0, size);
263	r = amdgpu_bo_cpu_unmap(vcn_bo->handle);
264	CU_ASSERT_EQUAL(r, 0);
265}
266
267static void free_resource(struct amdgpu_vcn_bo *vcn_bo)
268{
269	int r;
270
271	r = amdgpu_bo_va_op(vcn_bo->handle, 0, vcn_bo->size,
272			    vcn_bo->addr, 0, AMDGPU_VA_OP_UNMAP);
273	CU_ASSERT_EQUAL(r, 0);
274
275	r = amdgpu_va_range_free(vcn_bo->va_handle);
276	CU_ASSERT_EQUAL(r, 0);
277
278	r = amdgpu_bo_free(vcn_bo->handle);
279	CU_ASSERT_EQUAL(r, 0);
280	memset(vcn_bo, 0, sizeof(*vcn_bo));
281}
282
283static void vcn_dec_cmd(uint64_t addr, unsigned cmd, int *idx)
284{
285	ib_cpu[(*idx)++] = reg[vcn_reg_index].data0;
286	ib_cpu[(*idx)++] = addr;
287	ib_cpu[(*idx)++] = reg[vcn_reg_index].data1;
288	ib_cpu[(*idx)++] = addr >> 32;
289	ib_cpu[(*idx)++] = reg[vcn_reg_index].cmd;
290	ib_cpu[(*idx)++] = cmd << 1;
291}
292
293static void amdgpu_cs_vcn_dec_create(void)
294{
295	struct amdgpu_vcn_bo msg_buf;
296	int len, r;
297
298	num_resources  = 0;
299	alloc_resource(&msg_buf, 4096, AMDGPU_GEM_DOMAIN_GTT);
300	resources[num_resources++] = msg_buf.handle;
301	resources[num_resources++] = ib_handle;
302
303	r = amdgpu_bo_cpu_map(msg_buf.handle, (void **)&msg_buf.ptr);
304	CU_ASSERT_EQUAL(r, 0);
305
306	memset(msg_buf.ptr, 0, 4096);
307	memcpy(msg_buf.ptr, vcn_dec_create_msg, sizeof(vcn_dec_create_msg));
308
309	len = 0;
310	ib_cpu[len++] = reg[vcn_reg_index].data0;
311	ib_cpu[len++] = msg_buf.addr;
312	ib_cpu[len++] = reg[vcn_reg_index].data1;
313	ib_cpu[len++] = msg_buf.addr >> 32;
314	ib_cpu[len++] = reg[vcn_reg_index].cmd;
315	ib_cpu[len++] = 0;
316	for (; len % 16; ) {
317		ib_cpu[len++] = reg[vcn_reg_index].nop;
318		ib_cpu[len++] = 0;
319	}
320
321	r = submit(len, AMDGPU_HW_IP_VCN_DEC);
322	CU_ASSERT_EQUAL(r, 0);
323
324	free_resource(&msg_buf);
325}
326
327static void amdgpu_cs_vcn_dec_decode(void)
328{
329	const unsigned dpb_size = 15923584, dt_size = 737280;
330	uint64_t msg_addr, fb_addr, bs_addr, dpb_addr, ctx_addr, dt_addr, it_addr, sum;
331	struct amdgpu_vcn_bo dec_buf;
332	int size, len, i, r;
333	uint8_t *dec;
334
335	size = 4*1024; /* msg */
336	size += 4*1024; /* fb */
337	size += 4096; /*it_scaling_table*/
338	size += ALIGN(sizeof(uvd_bitstream), 4*1024);
339	size += ALIGN(dpb_size, 4*1024);
340	size += ALIGN(dt_size, 4*1024);
341
342	num_resources  = 0;
343	alloc_resource(&dec_buf, size, AMDGPU_GEM_DOMAIN_GTT);
344	resources[num_resources++] = dec_buf.handle;
345	resources[num_resources++] = ib_handle;
346
347	r = amdgpu_bo_cpu_map(dec_buf.handle, (void **)&dec_buf.ptr);
348	dec = dec_buf.ptr;
349
350	CU_ASSERT_EQUAL(r, 0);
351	memset(dec_buf.ptr, 0, size);
352	memcpy(dec_buf.ptr, vcn_dec_decode_msg, sizeof(vcn_dec_decode_msg));
353	memcpy(dec_buf.ptr + sizeof(vcn_dec_decode_msg),
354			avc_decode_msg, sizeof(avc_decode_msg));
355
356	dec += 4*1024;
357	memcpy(dec, feedback_msg, sizeof(feedback_msg));
358	dec += 4*1024;
359	memcpy(dec, uvd_it_scaling_table, sizeof(uvd_it_scaling_table));
360
361	dec += 4*1024;
362	memcpy(dec, uvd_bitstream, sizeof(uvd_bitstream));
363
364	dec += ALIGN(sizeof(uvd_bitstream), 4*1024);
365
366	dec += ALIGN(dpb_size, 4*1024);
367
368	msg_addr = dec_buf.addr;
369	fb_addr = msg_addr + 4*1024;
370	it_addr = fb_addr + 4*1024;
371	bs_addr = it_addr + 4*1024;
372	dpb_addr = ALIGN(bs_addr + sizeof(uvd_bitstream), 4*1024);
373	ctx_addr = ALIGN(dpb_addr + 0x006B9400, 4*1024);
374	dt_addr = ALIGN(dpb_addr + dpb_size, 4*1024);
375
376	len = 0;
377	vcn_dec_cmd(msg_addr, 0x0, &len);
378	vcn_dec_cmd(dpb_addr, 0x1, &len);
379	vcn_dec_cmd(dt_addr, 0x2, &len);
380	vcn_dec_cmd(fb_addr, 0x3, &len);
381	vcn_dec_cmd(bs_addr, 0x100, &len);
382	vcn_dec_cmd(it_addr, 0x204, &len);
383	vcn_dec_cmd(ctx_addr, 0x206, &len);
384
385	ib_cpu[len++] = reg[vcn_reg_index].cntl;
386	ib_cpu[len++] = 0x1;
387	for (; len % 16; ) {
388		ib_cpu[len++] = reg[vcn_reg_index].nop;
389		ib_cpu[len++] = 0;
390	}
391
392	r = submit(len, AMDGPU_HW_IP_VCN_DEC);
393	CU_ASSERT_EQUAL(r, 0);
394
395	for (i = 0, sum = 0; i < dt_size; ++i)
396		sum += dec[i];
397
398	CU_ASSERT_EQUAL(sum, SUM_DECODE);
399
400	free_resource(&dec_buf);
401}
402
403static void amdgpu_cs_vcn_dec_destroy(void)
404{
405	struct amdgpu_vcn_bo msg_buf;
406	int len, r;
407
408	num_resources  = 0;
409	alloc_resource(&msg_buf, 1024, AMDGPU_GEM_DOMAIN_GTT);
410	resources[num_resources++] = msg_buf.handle;
411	resources[num_resources++] = ib_handle;
412
413	r = amdgpu_bo_cpu_map(msg_buf.handle, (void **)&msg_buf.ptr);
414	CU_ASSERT_EQUAL(r, 0);
415
416	memset(msg_buf.ptr, 0, 1024);
417	memcpy(msg_buf.ptr, vcn_dec_destroy_msg, sizeof(vcn_dec_destroy_msg));
418
419	len = 0;
420	ib_cpu[len++] = reg[vcn_reg_index].data0;
421	ib_cpu[len++] = msg_buf.addr;
422	ib_cpu[len++] = reg[vcn_reg_index].data1;
423	ib_cpu[len++] = msg_buf.addr >> 32;
424	ib_cpu[len++] = reg[vcn_reg_index].cmd;
425	ib_cpu[len++] = 0;
426	for (; len % 16; ) {
427		ib_cpu[len++] = reg[vcn_reg_index].nop;
428		ib_cpu[len++] = 0;
429	}
430
431	r = submit(len, AMDGPU_HW_IP_VCN_DEC);
432	CU_ASSERT_EQUAL(r, 0);
433
434	free_resource(&msg_buf);
435}
436
437static void amdgpu_cs_vcn_enc_create(void)
438{
439	/* TODO */
440}
441
442static void amdgpu_cs_vcn_enc_encode(void)
443{
444	/* TODO */
445}
446
447static void amdgpu_cs_vcn_enc_destroy(void)
448{
449	/* TODO */
450}
451