Home | History | Annotate | Download | only in amdgpu
      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 "frame.h"
     35 #include "uve_ib.h"
     36 
     37 #define IB_SIZE		4096
     38 #define MAX_RESOURCES	16
     39 
     40 struct amdgpu_uvd_enc_bo {
     41 	amdgpu_bo_handle handle;
     42 	amdgpu_va_handle va_handle;
     43 	uint64_t addr;
     44 	uint64_t size;
     45 	uint8_t *ptr;
     46 };
     47 
     48 struct amdgpu_uvd_enc {
     49 	unsigned width;
     50 	unsigned height;
     51 	struct amdgpu_uvd_enc_bo session;
     52 	struct amdgpu_uvd_enc_bo vbuf;
     53 	struct amdgpu_uvd_enc_bo bs;
     54 	struct amdgpu_uvd_enc_bo fb;
     55 	struct amdgpu_uvd_enc_bo cpb;
     56 };
     57 
     58 static amdgpu_device_handle device_handle;
     59 static uint32_t major_version;
     60 static uint32_t minor_version;
     61 static uint32_t family_id;
     62 
     63 static amdgpu_context_handle context_handle;
     64 static amdgpu_bo_handle ib_handle;
     65 static amdgpu_va_handle ib_va_handle;
     66 static uint64_t ib_mc_address;
     67 static uint32_t *ib_cpu;
     68 
     69 static struct amdgpu_uvd_enc enc;
     70 static amdgpu_bo_handle resources[MAX_RESOURCES];
     71 static unsigned num_resources;
     72 
     73 static void amdgpu_cs_uvd_enc_create(void);
     74 static void amdgpu_cs_uvd_enc_session_init(void);
     75 static void amdgpu_cs_uvd_enc_encode(void);
     76 static void amdgpu_cs_uvd_enc_destroy(void);
     77 
     78 
     79 CU_TestInfo uvd_enc_tests[] = {
     80 	{ "UVD ENC create",  amdgpu_cs_uvd_enc_create },
     81 	{ "UVD ENC session init",  amdgpu_cs_uvd_enc_session_init },
     82 	{ "UVD ENC encode",  amdgpu_cs_uvd_enc_encode },
     83 	{ "UVD ENC destroy",  amdgpu_cs_uvd_enc_destroy },
     84 	CU_TEST_INFO_NULL,
     85 };
     86 
     87 CU_BOOL suite_uvd_enc_tests_enable(void)
     88 {
     89 	int r;
     90 	struct drm_amdgpu_info_hw_ip info;
     91 
     92 	if (amdgpu_device_initialize(drm_amdgpu[0], &major_version,
     93 					     &minor_version, &device_handle))
     94 		return CU_FALSE;
     95 
     96 	r = amdgpu_query_hw_ip_info(device_handle, AMDGPU_HW_IP_UVD_ENC, 0, &info);
     97 
     98 	if (amdgpu_device_deinitialize(device_handle))
     99 		return CU_FALSE;
    100 
    101 	if (!info.available_rings)
    102 		printf("\n\nThe ASIC NOT support UVD ENC, suite disabled.\n");
    103 
    104 	return (r == 0 && (info.available_rings ? CU_TRUE : CU_FALSE));
    105 }
    106 
    107 
    108 int suite_uvd_enc_tests_init(void)
    109 {
    110 	int r;
    111 
    112 	r = amdgpu_device_initialize(drm_amdgpu[0], &major_version,
    113 				     &minor_version, &device_handle);
    114 	if (r)
    115 		return CUE_SINIT_FAILED;
    116 
    117 	family_id = device_handle->info.family_id;
    118 
    119 	r = amdgpu_cs_ctx_create(device_handle, &context_handle);
    120 	if (r)
    121 		return CUE_SINIT_FAILED;
    122 
    123 	r = amdgpu_bo_alloc_and_map(device_handle, IB_SIZE, 4096,
    124 				    AMDGPU_GEM_DOMAIN_GTT, 0,
    125 				    &ib_handle, (void**)&ib_cpu,
    126 				    &ib_mc_address, &ib_va_handle);
    127 	if (r)
    128 		return CUE_SINIT_FAILED;
    129 
    130 	return CUE_SUCCESS;
    131 }
    132 
    133 int suite_uvd_enc_tests_clean(void)
    134 {
    135 	int r;
    136 
    137 	r = amdgpu_bo_unmap_and_free(ib_handle, ib_va_handle,
    138 				     ib_mc_address, IB_SIZE);
    139 	if (r)
    140 		return CUE_SCLEAN_FAILED;
    141 
    142 	r = amdgpu_cs_ctx_free(context_handle);
    143 	if (r)
    144 		return CUE_SCLEAN_FAILED;
    145 
    146 	r = amdgpu_device_deinitialize(device_handle);
    147 	if (r)
    148 		return CUE_SCLEAN_FAILED;
    149 
    150 	return CUE_SUCCESS;
    151 }
    152 
    153 static int submit(unsigned ndw, unsigned ip)
    154 {
    155 	struct amdgpu_cs_request ibs_request = {0};
    156 	struct amdgpu_cs_ib_info ib_info = {0};
    157 	struct amdgpu_cs_fence fence_status = {0};
    158 	uint32_t expired;
    159 	int r;
    160 
    161 	ib_info.ib_mc_address = ib_mc_address;
    162 	ib_info.size = ndw;
    163 
    164 	ibs_request.ip_type = ip;
    165 
    166 	r = amdgpu_bo_list_create(device_handle, num_resources, resources,
    167 				  NULL, &ibs_request.resources);
    168 	if (r)
    169 		return r;
    170 
    171 	ibs_request.number_of_ibs = 1;
    172 	ibs_request.ibs = &ib_info;
    173 	ibs_request.fence_info.handle = NULL;
    174 
    175 	r = amdgpu_cs_submit(context_handle, 0, &ibs_request, 1);
    176 	if (r)
    177 		return r;
    178 
    179 	r = amdgpu_bo_list_destroy(ibs_request.resources);
    180 	if (r)
    181 		return r;
    182 
    183 	fence_status.context = context_handle;
    184 	fence_status.ip_type = ip;
    185 	fence_status.fence = ibs_request.seq_no;
    186 
    187 	r = amdgpu_cs_query_fence_status(&fence_status,
    188 					 AMDGPU_TIMEOUT_INFINITE,
    189 					 0, &expired);
    190 	if (r)
    191 		return r;
    192 
    193 	return 0;
    194 }
    195 
    196 static void alloc_resource(struct amdgpu_uvd_enc_bo *uvd_enc_bo,
    197 			unsigned size, unsigned domain)
    198 {
    199 	struct amdgpu_bo_alloc_request req = {0};
    200 	amdgpu_bo_handle buf_handle;
    201 	amdgpu_va_handle va_handle;
    202 	uint64_t va = 0;
    203 	int r;
    204 
    205 	req.alloc_size = ALIGN(size, 4096);
    206 	req.preferred_heap = domain;
    207 	r = amdgpu_bo_alloc(device_handle, &req, &buf_handle);
    208 	CU_ASSERT_EQUAL(r, 0);
    209 	r = amdgpu_va_range_alloc(device_handle,
    210 				  amdgpu_gpu_va_range_general,
    211 				  req.alloc_size, 1, 0, &va,
    212 				  &va_handle, 0);
    213 	CU_ASSERT_EQUAL(r, 0);
    214 	r = amdgpu_bo_va_op(buf_handle, 0, req.alloc_size, va, 0,
    215 			    AMDGPU_VA_OP_MAP);
    216 	CU_ASSERT_EQUAL(r, 0);
    217 	uvd_enc_bo->addr = va;
    218 	uvd_enc_bo->handle = buf_handle;
    219 	uvd_enc_bo->size = req.alloc_size;
    220 	uvd_enc_bo->va_handle = va_handle;
    221 	r = amdgpu_bo_cpu_map(uvd_enc_bo->handle, (void **)&uvd_enc_bo->ptr);
    222 	CU_ASSERT_EQUAL(r, 0);
    223 	memset(uvd_enc_bo->ptr, 0, size);
    224 	r = amdgpu_bo_cpu_unmap(uvd_enc_bo->handle);
    225 	CU_ASSERT_EQUAL(r, 0);
    226 }
    227 
    228 static void free_resource(struct amdgpu_uvd_enc_bo *uvd_enc_bo)
    229 {
    230 	int r;
    231 
    232 	r = amdgpu_bo_va_op(uvd_enc_bo->handle, 0, uvd_enc_bo->size,
    233 			    uvd_enc_bo->addr, 0, AMDGPU_VA_OP_UNMAP);
    234 	CU_ASSERT_EQUAL(r, 0);
    235 
    236 	r = amdgpu_va_range_free(uvd_enc_bo->va_handle);
    237 	CU_ASSERT_EQUAL(r, 0);
    238 
    239 	r = amdgpu_bo_free(uvd_enc_bo->handle);
    240 	CU_ASSERT_EQUAL(r, 0);
    241 	memset(uvd_enc_bo, 0, sizeof(*uvd_enc_bo));
    242 }
    243 
    244 static void amdgpu_cs_uvd_enc_create(void)
    245 {
    246 	enc.width = 160;
    247 	enc.height = 128;
    248 
    249 	num_resources  = 0;
    250 	alloc_resource(&enc.session, 128 * 1024, AMDGPU_GEM_DOMAIN_GTT);
    251 	resources[num_resources++] = enc.session.handle;
    252 	resources[num_resources++] = ib_handle;
    253 }
    254 
    255 static void check_result(struct amdgpu_uvd_enc *enc)
    256 {
    257 	uint64_t sum;
    258 	uint32_t s = 175602;
    259 	uint32_t *ptr, size;
    260 	int j, r;
    261 
    262 	r = amdgpu_bo_cpu_map(enc->fb.handle, (void **)&enc->fb.ptr);
    263 	CU_ASSERT_EQUAL(r, 0);
    264 	ptr = (uint32_t *)enc->fb.ptr;
    265 	size = ptr[6];
    266 	r = amdgpu_bo_cpu_unmap(enc->fb.handle);
    267 	CU_ASSERT_EQUAL(r, 0);
    268 	r = amdgpu_bo_cpu_map(enc->bs.handle, (void **)&enc->bs.ptr);
    269 	CU_ASSERT_EQUAL(r, 0);
    270 	for (j = 0, sum = 0; j < size; ++j)
    271 		sum += enc->bs.ptr[j];
    272 	CU_ASSERT_EQUAL(sum, s);
    273 	r = amdgpu_bo_cpu_unmap(enc->bs.handle);
    274 	CU_ASSERT_EQUAL(r, 0);
    275 
    276 }
    277 
    278 static void amdgpu_cs_uvd_enc_session_init(void)
    279 {
    280 	int len, r;
    281 
    282 	len = 0;
    283 	memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info));
    284 	len += sizeof(uve_session_info) / 4;
    285 	ib_cpu[len++] = enc.session.addr >> 32;
    286 	ib_cpu[len++] = enc.session.addr;
    287 
    288 	memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info));
    289 	len += sizeof(uve_task_info) / 4;
    290 	ib_cpu[len++] = 0x000000d8;
    291 	ib_cpu[len++] = 0x00000000;
    292 	ib_cpu[len++] = 0x00000000;
    293 
    294 	memcpy((ib_cpu + len), uve_op_init, sizeof(uve_op_init));
    295 	len += sizeof(uve_op_init) / 4;
    296 
    297 	memcpy((ib_cpu + len), uve_session_init, sizeof(uve_session_init));
    298 	len += sizeof(uve_session_init) / 4;
    299 
    300 	memcpy((ib_cpu + len), uve_layer_ctrl, sizeof(uve_layer_ctrl));
    301 	len += sizeof(uve_layer_ctrl) / 4;
    302 
    303 	memcpy((ib_cpu + len), uve_slice_ctrl, sizeof(uve_slice_ctrl));
    304 	len += sizeof(uve_slice_ctrl) / 4;
    305 
    306 	memcpy((ib_cpu + len), uve_spec_misc, sizeof(uve_spec_misc));
    307 	len += sizeof(uve_spec_misc) / 4;
    308 
    309 	memcpy((ib_cpu + len), uve_rc_session_init, sizeof(uve_rc_session_init));
    310 	len += sizeof(uve_rc_session_init) / 4;
    311 
    312 	memcpy((ib_cpu + len), uve_deblocking_filter, sizeof(uve_deblocking_filter));
    313 	len += sizeof(uve_deblocking_filter) / 4;
    314 
    315 	memcpy((ib_cpu + len), uve_quality_params, sizeof(uve_quality_params));
    316 	len += sizeof(uve_quality_params) / 4;
    317 
    318 	memcpy((ib_cpu + len), uve_op_init_rc, sizeof(uve_op_init_rc));
    319 	len += sizeof(uve_op_init_rc) / 4;
    320 
    321 	memcpy((ib_cpu + len), uve_op_init_rc_vbv_level, sizeof(uve_op_init_rc_vbv_level));
    322 	len += sizeof(uve_op_init_rc_vbv_level) / 4;
    323 
    324 	r = submit(len, AMDGPU_HW_IP_UVD_ENC);
    325 	CU_ASSERT_EQUAL(r, 0);
    326 }
    327 
    328 static void amdgpu_cs_uvd_enc_encode(void)
    329 {
    330 	int len, r, i;
    331 	uint64_t luma_offset, chroma_offset;
    332 	uint32_t vbuf_size, bs_size = 0x003f4800, cpb_size;
    333 	unsigned align = (family_id >= AMDGPU_FAMILY_AI) ? 256 : 16;
    334 	vbuf_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16) * 1.5;
    335 	cpb_size = vbuf_size * 10;
    336 
    337 
    338 	num_resources  = 0;
    339 	alloc_resource(&enc.fb, 4096, AMDGPU_GEM_DOMAIN_VRAM);
    340 	resources[num_resources++] = enc.fb.handle;
    341 	alloc_resource(&enc.bs, bs_size, AMDGPU_GEM_DOMAIN_VRAM);
    342 	resources[num_resources++] = enc.bs.handle;
    343 	alloc_resource(&enc.vbuf, vbuf_size, AMDGPU_GEM_DOMAIN_VRAM);
    344 	resources[num_resources++] = enc.vbuf.handle;
    345 	alloc_resource(&enc.cpb, cpb_size, AMDGPU_GEM_DOMAIN_VRAM);
    346 	resources[num_resources++] = enc.cpb.handle;
    347 	resources[num_resources++] = ib_handle;
    348 
    349 	r = amdgpu_bo_cpu_map(enc.vbuf.handle, (void **)&enc.vbuf.ptr);
    350 	CU_ASSERT_EQUAL(r, 0);
    351 
    352 	memset(enc.vbuf.ptr, 0, vbuf_size);
    353 	for (i = 0; i < enc.height; ++i) {
    354 		memcpy(enc.vbuf.ptr, (frame + i * enc.width), enc.width);
    355 		enc.vbuf.ptr += ALIGN(enc.width, align);
    356 	}
    357 	for (i = 0; i < enc.height / 2; ++i) {
    358 		memcpy(enc.vbuf.ptr, ((frame + enc.height * enc.width) + i * enc.width), enc.width);
    359 		enc.vbuf.ptr += ALIGN(enc.width, align);
    360 	}
    361 
    362 	r = amdgpu_bo_cpu_unmap(enc.vbuf.handle);
    363 	CU_ASSERT_EQUAL(r, 0);
    364 
    365 	len = 0;
    366 	memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info));
    367 	len += sizeof(uve_session_info) / 4;
    368 	ib_cpu[len++] = enc.session.addr >> 32;
    369 	ib_cpu[len++] = enc.session.addr;
    370 
    371 	memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info));
    372 	len += sizeof(uve_task_info) / 4;
    373 	ib_cpu[len++] = 0x000005e0;
    374 	ib_cpu[len++] = 0x00000001;
    375 	ib_cpu[len++] = 0x00000001;
    376 
    377 	memcpy((ib_cpu + len), uve_nalu_buffer_1, sizeof(uve_nalu_buffer_1));
    378 	len += sizeof(uve_nalu_buffer_1) / 4;
    379 
    380 	memcpy((ib_cpu + len), uve_nalu_buffer_2, sizeof(uve_nalu_buffer_2));
    381 	len += sizeof(uve_nalu_buffer_2) / 4;
    382 
    383 	memcpy((ib_cpu + len), uve_nalu_buffer_3, sizeof(uve_nalu_buffer_3));
    384 	len += sizeof(uve_nalu_buffer_3) / 4;
    385 
    386 	memcpy((ib_cpu + len), uve_nalu_buffer_4, sizeof(uve_nalu_buffer_4));
    387 	len += sizeof(uve_nalu_buffer_4) / 4;
    388 
    389 	memcpy((ib_cpu + len), uve_slice_header, sizeof(uve_slice_header));
    390 	len += sizeof(uve_slice_header) / 4;
    391 
    392 	ib_cpu[len++] = 0x00000254;
    393 	ib_cpu[len++] = 0x00000010;
    394 	ib_cpu[len++] = enc.cpb.addr >> 32;
    395 	ib_cpu[len++] = enc.cpb.addr;
    396 	memcpy((ib_cpu + len), uve_ctx_buffer, sizeof(uve_ctx_buffer));
    397 	len += sizeof(uve_ctx_buffer) / 4;
    398 
    399 	memcpy((ib_cpu + len), uve_bitstream_buffer, sizeof(uve_bitstream_buffer));
    400 	len += sizeof(uve_bitstream_buffer) / 4;
    401 	ib_cpu[len++] = 0x00000000;
    402 	ib_cpu[len++] = enc.bs.addr >> 32;
    403 	ib_cpu[len++] = enc.bs.addr;
    404 	ib_cpu[len++] = 0x003f4800;
    405 	ib_cpu[len++] = 0x00000000;
    406 
    407 	memcpy((ib_cpu + len), uve_feedback_buffer, sizeof(uve_feedback_buffer));
    408 	len += sizeof(uve_feedback_buffer) / 4;
    409 	ib_cpu[len++] = enc.fb.addr >> 32;
    410 	ib_cpu[len++] = enc.fb.addr;
    411 	ib_cpu[len++] = 0x00000010;
    412 	ib_cpu[len++] = 0x00000028;
    413 
    414 	memcpy((ib_cpu + len), uve_feedback_buffer_additional, sizeof(uve_feedback_buffer_additional));
    415 	len += sizeof(uve_feedback_buffer_additional) / 4;
    416 
    417 	memcpy((ib_cpu + len), uve_intra_refresh, sizeof(uve_intra_refresh));
    418 	len += sizeof(uve_intra_refresh) / 4;
    419 
    420 	memcpy((ib_cpu + len), uve_layer_select, sizeof(uve_layer_select));
    421 	len += sizeof(uve_layer_select) / 4;
    422 
    423 	memcpy((ib_cpu + len), uve_rc_layer_init, sizeof(uve_rc_layer_init));
    424 	len += sizeof(uve_rc_layer_init) / 4;
    425 
    426 	memcpy((ib_cpu + len), uve_layer_select, sizeof(uve_layer_select));
    427 	len += sizeof(uve_layer_select) / 4;
    428 
    429 	memcpy((ib_cpu + len), uve_rc_per_pic, sizeof(uve_rc_per_pic));
    430 	len += sizeof(uve_rc_per_pic) / 4;
    431 
    432 	unsigned luma_size = ALIGN(enc.width, align) * ALIGN(enc.height, 16);
    433 	luma_offset = enc.vbuf.addr;
    434 	chroma_offset = luma_offset + luma_size;
    435 	ib_cpu[len++] = 0x00000054;
    436 	ib_cpu[len++] = 0x0000000c;
    437 	ib_cpu[len++] = 0x00000002;
    438 	ib_cpu[len++] = 0x003f4800;
    439 	ib_cpu[len++] = luma_offset >> 32;
    440 	ib_cpu[len++] = luma_offset;
    441 	ib_cpu[len++] = chroma_offset >> 32;
    442 	ib_cpu[len++] = chroma_offset;
    443 	memcpy((ib_cpu + len), uve_encode_param, sizeof(uve_encode_param));
    444 	ib_cpu[len] = ALIGN(enc.width, align);
    445 	ib_cpu[len + 1] = ALIGN(enc.width, align);
    446 	len += sizeof(uve_encode_param) / 4;
    447 
    448 	memcpy((ib_cpu + len), uve_op_speed_enc_mode, sizeof(uve_op_speed_enc_mode));
    449 	len += sizeof(uve_op_speed_enc_mode) / 4;
    450 
    451 	memcpy((ib_cpu + len), uve_op_encode, sizeof(uve_op_encode));
    452 	len += sizeof(uve_op_encode) / 4;
    453 
    454 	r = submit(len, AMDGPU_HW_IP_UVD_ENC);
    455 	CU_ASSERT_EQUAL(r, 0);
    456 
    457 	check_result(&enc);
    458 
    459 	free_resource(&enc.fb);
    460 	free_resource(&enc.bs);
    461 	free_resource(&enc.vbuf);
    462 	free_resource(&enc.cpb);
    463 }
    464 
    465 static void amdgpu_cs_uvd_enc_destroy(void)
    466 {
    467 	int len, r;
    468 
    469 	num_resources  = 0;
    470 	resources[num_resources++] = ib_handle;
    471 
    472 	len = 0;
    473 	memcpy((ib_cpu + len), uve_session_info, sizeof(uve_session_info));
    474 	len += sizeof(uve_session_info) / 4;
    475 	ib_cpu[len++] = enc.session.addr >> 32;
    476 	ib_cpu[len++] = enc.session.addr;
    477 
    478 	memcpy((ib_cpu + len), uve_task_info, sizeof(uve_task_info));
    479 	len += sizeof(uve_task_info) / 4;
    480 	ib_cpu[len++] = 0xffffffff;
    481 	ib_cpu[len++] = 0x00000002;
    482 	ib_cpu[len++] = 0x00000000;
    483 
    484 	memcpy((ib_cpu + len), uve_op_close, sizeof(uve_op_close));
    485 	len += sizeof(uve_op_close) / 4;
    486 
    487 	r = submit(len, AMDGPU_HW_IP_UVD_ENC);
    488 	CU_ASSERT_EQUAL(r, 0);
    489 
    490 	free_resource(&enc.session);
    491 }
    492