1 /* 2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 3 * Copyright (c) Imagination Technologies Limited, UK 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 * Authors: 26 * Waldo Bastian <waldo.bastian (at) intel.com> 27 * Zeng Li <zeng.li (at) intel.com> 28 * Edward Lin <edward.lin (at) intel.com> 29 * 30 */ 31 32 #include <unistd.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <errno.h> 36 #include <string.h> 37 #include <wsbm/wsbm_manager.h> 38 #include "psb_buffer.h" 39 #include "tng_cmdbuf.h" 40 #include "psb_def.h" 41 #include "psb_drv_debug.h" 42 #include "tng_hostcode.h" 43 #include "psb_ws_driver.h" 44 45 #ifdef ANDROID 46 #include <linux/psb_drm.h> 47 #else 48 #include "psb_drm.h" 49 #endif 50 51 #include "tng_trace.h" 52 53 /* 54 * Buffer layout: 55 * cmd_base <= cmd_idx < CMD_END() == reloc_base 56 * reloc_base <= reloc_idx < RELOC_END() == (reloc_size) 57 */ 58 59 #define RELOC_END(cmdbuf) (cmdbuf->cmd_base + cmdbuf->size) 60 #define CMD_END(cmdbuf) (cmdbuf->reloc_base) 61 #define RELOC_SIZE (0x3000) 62 #define CMD_SIZE (0x3000) 63 #define RELOC_MARGIN (0x0800) 64 #define CMD_MARGIN (0x0400) 65 #define MAX_CMD_COUNT 12 66 #define MTX_SEG_SIZE (0x0800) 67 68 /*! 69 ***************************************************************************** 70 * 71 * @Name Command word format 72 * 73 * @details Mask and shift values for command word 74 * 75 ****************************************************************************/ 76 77 /* 78 * clear buffer 79 */ 80 void tng_cmdbuf_mem_unmap(tng_cmdbuf_p cmdbuf) 81 { 82 psb_buffer_unmap(&cmdbuf->frame_mem); 83 psb_buffer_unmap(&cmdbuf->jpeg_pic_params); 84 psb_buffer_unmap(&cmdbuf->jpeg_header_mem); 85 psb_buffer_unmap(&cmdbuf->jpeg_header_interface_mem); 86 return ; 87 } 88 89 /* 90 * clear buffer 91 */ 92 static void tng_cmdbuf_clear(tng_cmdbuf_p cmdbuf, int flag) 93 { 94 switch (flag) { 95 default: 96 case 4: 97 psb_buffer_destroy(&cmdbuf->jpeg_header_mem); 98 case 3: 99 psb_buffer_destroy(&cmdbuf->jpeg_pic_params); 100 case 2: 101 case 1: 102 psb_buffer_destroy(&cmdbuf->frame_mem); 103 break; 104 } 105 106 if (cmdbuf->size) { 107 psb_buffer_destroy(&cmdbuf->buf); 108 cmdbuf->size = 0; 109 } 110 if (cmdbuf->buffer_refs_allocated) { 111 free(cmdbuf->buffer_refs); 112 cmdbuf->buffer_refs = NULL; 113 cmdbuf->buffer_refs_allocated = 0; 114 } 115 } 116 117 118 /* 119 * Create command buffer 120 */ 121 122 VAStatus tng_cmdbuf_create( 123 object_context_p obj_context, 124 psb_driver_data_p driver_data, 125 tng_cmdbuf_p cmdbuf) 126 { 127 context_ENC_p ctx = (context_ENC_p) obj_context->format_data; 128 129 VAStatus vaStatus = VA_STATUS_SUCCESS; 130 unsigned int size = CMD_SIZE + RELOC_SIZE; 131 132 cmdbuf->size = 0; 133 cmdbuf->cmd_base = NULL; 134 cmdbuf->cmd_idx = NULL; 135 cmdbuf->reloc_base = NULL; 136 cmdbuf->reloc_idx = NULL; 137 cmdbuf->buffer_refs_count = 0; 138 cmdbuf->buffer_refs_allocated = 10; 139 cmdbuf->buffer_refs = (psb_buffer_p *) calloc(1, sizeof(psb_buffer_p) * cmdbuf->buffer_refs_allocated); 140 if (NULL == cmdbuf->buffer_refs) { 141 cmdbuf->buffer_refs_allocated = 0; 142 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 143 } 144 145 if (VA_STATUS_SUCCESS == vaStatus) { 146 vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_only, &cmdbuf->buf); 147 cmdbuf->size = size; 148 } 149 150 if (VA_STATUS_SUCCESS != vaStatus) { 151 drv_debug_msg(VIDEO_DEBUG_ERROR, "psb buffer create 0 \n", __FUNCTION__); 152 tng_cmdbuf_clear(cmdbuf, 1); 153 free(cmdbuf->buffer_refs); 154 cmdbuf->buffer_refs = NULL; 155 cmdbuf->buffer_refs_allocated = 0; 156 return vaStatus; 157 } 158 159 cmdbuf->mem_size = tng_align_KB(TNG_HEADER_SIZE); 160 drv_debug_msg(VIDEO_DEBUG_GENERAL, "mem size %d\n", __FUNCTION__, cmdbuf->mem_size); 161 /* create buffer information buffer */ 162 //DEBUG-FIXME 163 //tng__alloc_init_buffer(driver_data, COMM_CMD_FRAME_BUF_NUM * cmdbuf->mem_size, psb_bt_cpu_vpu, &cmdbuf->frame_mem); 164 165 vaStatus = psb_buffer_create(driver_data, COMM_CMD_FRAME_BUF_NUM * cmdbuf->mem_size, psb_bt_cpu_vpu, &cmdbuf->frame_mem); 166 if (VA_STATUS_SUCCESS != vaStatus) { 167 drv_debug_msg(VIDEO_DEBUG_ERROR, "psb buffer create xx \n", __FUNCTION__); 168 free(cmdbuf->buffer_refs); 169 cmdbuf->buffer_refs = NULL; 170 cmdbuf->buffer_refs_allocated = 0; 171 return vaStatus; 172 } 173 /* all cmdbuf share one MTX_CURRENT_IN_PARAMS since every MB has a MTX_CURRENT_IN_PARAMS structure 174 * and filling this structure for all MB is very time-consuming 175 */ 176 177 /* create JPEG quantization buffer */ 178 vaStatus = psb_buffer_create(driver_data, ctx->jpeg_pic_params_size, psb_bt_cpu_vpu, &cmdbuf->jpeg_pic_params); 179 if (VA_STATUS_SUCCESS != vaStatus) { 180 drv_debug_msg(VIDEO_DEBUG_ERROR, "psb buffer create 1 \n", __FUNCTION__); 181 tng_cmdbuf_clear(cmdbuf, 2); 182 return vaStatus; 183 } 184 185 /* create JPEG MTX setup buffer */ 186 vaStatus = psb_buffer_create(driver_data, ctx->jpeg_header_mem_size, psb_bt_cpu_vpu, &cmdbuf->jpeg_header_mem); 187 if (VA_STATUS_SUCCESS != vaStatus) { 188 drv_debug_msg(VIDEO_DEBUG_ERROR, "psb buffer create 2 \n", __FUNCTION__); 189 tng_cmdbuf_clear(cmdbuf, 3); 190 return vaStatus; 191 } 192 193 /* create JPEG MTX setup interface buffer */ 194 vaStatus = psb_buffer_create(driver_data, ctx->jpeg_header_interface_mem_size, psb_bt_cpu_vpu, &cmdbuf->jpeg_header_interface_mem); 195 if (VA_STATUS_SUCCESS != vaStatus) { 196 drv_debug_msg(VIDEO_DEBUG_ERROR, "psb buffer create 3 \n", __FUNCTION__); 197 tng_cmdbuf_clear(cmdbuf, 4); 198 return vaStatus; 199 } 200 201 return vaStatus; 202 } 203 204 /* 205 * Destroy buffer 206 */ 207 void tng_cmdbuf_destroy(tng_cmdbuf_p cmdbuf) 208 { 209 psb_buffer_destroy(&cmdbuf->frame_mem); 210 psb_buffer_destroy(&cmdbuf->jpeg_header_mem); 211 psb_buffer_destroy(&cmdbuf->jpeg_pic_params); 212 psb_buffer_destroy(&cmdbuf->jpeg_header_interface_mem); 213 214 if (cmdbuf->size) { 215 psb_buffer_destroy(&cmdbuf->buf); 216 cmdbuf->size = 0; 217 } 218 if (cmdbuf->buffer_refs_allocated) { 219 free(cmdbuf->buffer_refs); 220 cmdbuf->buffer_refs = NULL; 221 cmdbuf->buffer_refs_allocated = 0; 222 } 223 return ; 224 } 225 226 /* 227 * Reset buffer & map 228 * 229 * Returns 0 on success 230 */ 231 int tng_cmdbuf_reset(tng_cmdbuf_p cmdbuf) 232 { 233 int ret; 234 cmdbuf->cmd_base = NULL; 235 cmdbuf->cmd_idx = NULL; 236 cmdbuf->reloc_base = NULL; 237 cmdbuf->reloc_idx = NULL; 238 239 cmdbuf->buffer_refs_count = 0; 240 cmdbuf->frame_mem_index = 0; 241 cmdbuf->cmd_count = 0; 242 cmdbuf->mem_size = tng_align_KB(TNG_HEADER_SIZE); 243 244 ret = psb_buffer_map(&cmdbuf->buf, &cmdbuf->cmd_base); 245 if (ret) { 246 return ret; 247 } 248 249 cmdbuf->cmd_start = cmdbuf->cmd_base; 250 cmdbuf->cmd_idx = (IMG_UINT32 *) cmdbuf->cmd_base; 251 252 cmdbuf->reloc_base = cmdbuf->cmd_base + CMD_SIZE; 253 cmdbuf->reloc_idx = (struct drm_psb_reloc *) cmdbuf->reloc_base; 254 255 /* Add ourselves to the buffer list */ 256 tng_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->buf); /* cmd buf == 0 */ 257 return ret; 258 } 259 260 /* 261 * Unmap buffer 262 * 263 * Returns 0 on success 264 */ 265 int tng_cmdbuf_unmap(tng_cmdbuf_p cmdbuf) 266 { 267 cmdbuf->cmd_base = NULL; 268 cmdbuf->cmd_start = NULL; 269 cmdbuf->cmd_idx = NULL; 270 cmdbuf->reloc_base = NULL; 271 cmdbuf->reloc_idx = NULL; 272 cmdbuf->cmd_count = 0; 273 psb_buffer_unmap(&cmdbuf->buf); 274 return 0; 275 } 276 277 278 /* 279 * Reference an addtional buffer "buf" in the command stream 280 * Returns a reference index that can be used to refer to "buf" in 281 * relocation records, -1 on error 282 */ 283 int tng_cmdbuf_buffer_ref(tng_cmdbuf_p cmdbuf, psb_buffer_p buf) 284 { 285 int item_loc = 0; 286 287 /*Reserve the same TTM BO twice will cause kernel lock up*/ 288 while ((item_loc < cmdbuf->buffer_refs_count) 289 && (wsbmKBufHandle(wsbmKBuf(cmdbuf->buffer_refs[item_loc]->drm_buf)) 290 != wsbmKBufHandle(wsbmKBuf(buf->drm_buf)))) 291 //while( (item_loc < cmdbuf->buffer_refs_count) && (cmdbuf->buffer_refs[item_loc] != buf) ) 292 { 293 item_loc++; 294 } 295 if (item_loc == cmdbuf->buffer_refs_count) { 296 /* Add new entry */ 297 if (item_loc >= cmdbuf->buffer_refs_allocated) { 298 /* Allocate more entries */ 299 int new_size = cmdbuf->buffer_refs_allocated + 10; 300 psb_buffer_p *new_array; 301 new_array = (psb_buffer_p *) calloc(1, sizeof(psb_buffer_p) * new_size); 302 if (NULL == new_array) { 303 return -1; /* Allocation failure */ 304 } 305 memcpy(new_array, cmdbuf->buffer_refs, sizeof(psb_buffer_p) * cmdbuf->buffer_refs_allocated); 306 free(cmdbuf->buffer_refs); 307 cmdbuf->buffer_refs_allocated = new_size; 308 cmdbuf->buffer_refs = new_array; 309 } 310 cmdbuf->buffer_refs[item_loc] = buf; 311 cmdbuf->buffer_refs_count++; 312 buf->status = psb_bs_queued; 313 } 314 return item_loc; 315 } 316 317 /* Creates a relocation record for a DWORD in the mapped "cmdbuf" at address 318 * "addr_in_cmdbuf" 319 * The relocation is based on the device virtual address of "ref_buffer" 320 * "buf_offset" is be added to the device virtual address, and the sum is then 321 * right shifted with "align_shift". 322 * "mask" determines which bits of the target DWORD will be updated with the so 323 * constructed address. The remaining bits will be filled with bits from "background". 324 */ 325 void tng_cmdbuf_add_relocation(tng_cmdbuf_p cmdbuf, 326 IMG_UINT32 *addr_in_dst_buffer,/*addr of dst_buffer for the DWORD*/ 327 psb_buffer_p ref_buffer, 328 IMG_UINT32 buf_offset, 329 IMG_UINT32 mask, 330 IMG_UINT32 background, 331 IMG_UINT32 align_shift, 332 IMG_UINT32 dst_buffer, 333 IMG_UINT32 *start_of_dst_buffer) /*Index of the list refered by cmdbuf->buffer_refs */ 334 { 335 struct drm_psb_reloc *reloc = cmdbuf->reloc_idx; 336 uint64_t presumed_offset = wsbmBOOffsetHint(ref_buffer->drm_buf); 337 338 reloc->where = addr_in_dst_buffer - start_of_dst_buffer; /* Offset in DWORDs */ 339 340 reloc->buffer = tng_cmdbuf_buffer_ref(cmdbuf, ref_buffer); 341 ASSERT(reloc->buffer != -1); 342 343 reloc->reloc_op = PSB_RELOC_OP_OFFSET; 344 #ifndef VA_EMULATOR 345 if (presumed_offset) { 346 IMG_UINT32 new_val = presumed_offset + buf_offset; 347 348 new_val = ((new_val >> align_shift) << (align_shift << PSB_RELOC_ALSHIFT_SHIFT)); 349 new_val = (background & ~mask) | (new_val & mask); 350 *addr_in_dst_buffer = new_val; 351 } else { 352 *addr_in_dst_buffer = PSB_RELOC_MAGIC; 353 } 354 #else 355 /* indicate subscript of relocation buffer */ 356 *addr_in_dst_buffer = reloc - (struct drm_psb_reloc *)cmdbuf->reloc_base; 357 #endif 358 reloc->mask = mask; 359 reloc->shift = align_shift << PSB_RELOC_ALSHIFT_SHIFT; 360 reloc->pre_add = buf_offset; 361 reloc->background = background; 362 reloc->dst_buffer = dst_buffer; 363 cmdbuf->reloc_idx++; 364 365 ASSERT(((void *)(cmdbuf->reloc_idx)) < RELOC_END(cmdbuf)); 366 } 367 368 /* Prepare one command package */ 369 void tng_cmdbuf_insert_command( 370 object_context_p obj_context, 371 IMG_UINT32 stream_id, 372 IMG_UINT32 cmd_id, 373 IMG_UINT32 cmd_data, 374 psb_buffer_p data_addr, 375 IMG_UINT32 offset) 376 { 377 IMG_UINT32 cmd_word; 378 context_ENC_p ctx = (context_ENC_p) obj_context->format_data; 379 context_ENC_cmdbuf *ps_cmd = &(ctx->ctx_cmdbuf[stream_id]); 380 context_ENC_mem *ps_mem = &(ctx->ctx_mem[stream_id]); 381 tng_cmdbuf_p cmdbuf = obj_context->tng_cmdbuf; 382 psb_driver_data_p driver_data = ctx->obj_context->driver_data; 383 int interrupt_flags; 384 385 //CMD composed by user space does not generate Interrupt 386 interrupt_flags = 0; 387 388 assert(stream_id <= TOPAZHP_MAX_NUM_STREAMS); 389 390 /* Write command to FIFO */ 391 { 392 cmd_word = F_ENCODE(stream_id, MTX_MSG_CORE) | 393 F_ENCODE(cmd_id, MTX_MSG_CMD_ID); 394 395 if (cmd_id & MTX_CMDID_PRIORITY) { 396 /* increment the command counter */ 397 ps_cmd->ui32HighCmdCount++; 398 399 /* Prepare high priority command */ 400 cmd_word |= F_ENCODE(1, MTX_MSG_PRIORITY) | 401 F_ENCODE(((ps_cmd->ui32LowCmdCount - 1) & 0xff) |(ps_cmd->ui32HighCmdCount << 8), MTX_MSG_COUNT); 402 } else { 403 /* Prepare low priority command */ 404 cmd_word |= 405 F_ENCODE(ps_cmd->ui32LowCmdCount & 0xff, MTX_MSG_COUNT); 406 ++(ps_cmd->ui32LowCmdCount); 407 } 408 drv_debug_msg(VIDEO_DEBUG_GENERAL, 409 "%s: cmd_id = 0x%08x\n", 410 __FUNCTION__, cmd_word); 411 *cmdbuf->cmd_idx++ = cmd_word; 412 } 413 414 /* write command word into cmdbuf */ 415 *cmdbuf->cmd_idx++ = cmd_data; 416 /* Command data address */ 417 if (data_addr) { 418 if (cmd_id == MTX_CMDID_RC_UPDATE) { 419 *cmdbuf->cmd_idx++ = (IMG_UINT32)data_addr; 420 drv_debug_msg(VIDEO_DEBUG_GENERAL, 421 "%s: data_addr = 0x%08x\n", 422 __FUNCTION__, *(cmdbuf->cmd_idx)); 423 } else { 424 if ((cmd_id >= MTX_CMDID_SETQUANT) && (cmd_id <= MTX_CMDID_SETUP)) { 425 if (cmd_id == MTX_CMDID_ISSUEBUFF) 426 TNG_RELOC_CMDBUF_START(cmdbuf->cmd_idx, offset, data_addr); 427 else 428 tng_cmdbuf_set_phys(cmdbuf->cmd_idx, 0, data_addr, offset, 0); 429 } else { 430 #ifdef _TNG_RELOC_ 431 TNG_RELOC_CMDBUF_START(cmdbuf->cmd_idx, offset, data_addr); 432 #else 433 tng_cmdbuf_set_phys(cmdbuf->cmd_idx, 0, data_addr, offset, 0); 434 #endif 435 } 436 drv_debug_msg(VIDEO_DEBUG_GENERAL, 437 "%s: data_addr = 0x%08x\n", 438 __FUNCTION__, *(cmdbuf->cmd_idx)); 439 cmdbuf->cmd_idx++; 440 } 441 } else { 442 *cmdbuf->cmd_idx++ = 0; 443 } 444 445 if (cmd_id == MTX_CMDID_SW_FILL_INPUT_CTRL) { 446 *cmdbuf->cmd_idx++ = ctx->ui16IntraRefresh; 447 *cmdbuf->cmd_idx++ = ctx->sRCParams.ui32InitialQp; 448 *cmdbuf->cmd_idx++ = ctx->sRCParams.iMinQP; 449 *cmdbuf->cmd_idx++ = ctx->ctx_mem_size.mb_ctrl_in_params; 450 *cmdbuf->cmd_idx++ = ctx->ui32pseudo_rand_seed; 451 } 452 453 if (cmd_id == MTX_CMDID_SW_UPDATE_AIR_SEND) { 454 *cmdbuf->cmd_idx++ = ctx->sAirInfo.i16AIRSkipCnt; 455 *cmdbuf->cmd_idx++ = ctx->sAirInfo.i32NumAIRSPerFrame; 456 *cmdbuf->cmd_idx++ = ctx->ctx_mem_size.mb_ctrl_in_params; 457 *cmdbuf->cmd_idx++ = ctx->ui32FrameCount[0]; 458 } 459 460 if (cmd_id == MTX_CMDID_SW_UPDATE_AIR_CALC) { 461 *cmdbuf->cmd_idx++ = ctx->ctx_mem_size.first_pass_out_best_multipass_param; 462 *cmdbuf->cmd_idx++ = ctx->sAirInfo.i32SAD_Threshold; 463 *cmdbuf->cmd_idx++ = ctx->ui8EnableSelStatsFlags; 464 } 465 466 /* Command data address */ 467 if (cmd_id == MTX_CMDID_SETVIDEO) { 468 *(cmdbuf->cmd_idx)++ = wsbmKBufHandle(wsbmKBuf(ctx->bufs_writeback.drm_buf)); 469 drv_debug_msg(VIDEO_DEBUG_GENERAL, 470 "%s: cmd_param = 0x%08x\n", 471 __FUNCTION__, *(cmdbuf->cmd_idx - 1)); 472 473 if (data_addr) 474 *(cmdbuf->cmd_idx)++ = wsbmKBufHandle(wsbmKBuf(data_addr->drm_buf)); 475 476 *(cmdbuf->cmd_idx)++ = wsbmKBufHandle(wsbmKBuf(ps_mem->bufs_mb_ctrl_in_params.drm_buf)); 477 *(cmdbuf->cmd_idx)++ = wsbmKBufHandle(wsbmKBuf(ps_mem->bufs_first_pass_out_params.drm_buf)); 478 *(cmdbuf->cmd_idx)++ = wsbmKBufHandle(wsbmKBuf(ps_mem->bufs_first_pass_out_best_multipass_param.drm_buf)); 479 } 480 481 if (cmd_id == MTX_CMDID_SETUP_INTERFACE) { 482 *(cmdbuf->cmd_idx)++ = wsbmKBufHandle(wsbmKBuf(ctx->bufs_writeback.drm_buf)); 483 drv_debug_msg(VIDEO_DEBUG_GENERAL, 484 "%s: cmd_param = 0x%08x\n", 485 __FUNCTION__, *(cmdbuf->cmd_idx - 1)); 486 } 487 488 if (cmd_id == MTX_CMDID_SHUTDOWN) { 489 *(cmdbuf->cmd_idx)++ = ctx->eCodec; 490 491 drv_debug_msg(VIDEO_DEBUG_GENERAL, 492 "%s: cmd_param = 0x%08x\n", 493 __FUNCTION__, *(cmdbuf->cmd_idx - 1)); 494 } 495 496 return ; 497 } 498 499 500 /* 501 * Advances "obj_context" to the next cmdbuf 502 * 503 * Returns 0 on success 504 */ 505 int tng_context_get_next_cmdbuf(object_context_p obj_context) 506 { 507 tng_cmdbuf_p cmdbuf; 508 int ret; 509 510 drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: start obj_context->tng_cmdbuf = %x\n", __FUNCTION__, obj_context->tng_cmdbuf); 511 512 if (obj_context->tng_cmdbuf) { 513 return 0; 514 } 515 516 obj_context->cmdbuf_current++; 517 if (obj_context->cmdbuf_current >= TNG_MAX_CMDBUFS_ENCODE) { 518 obj_context->cmdbuf_current = 0; 519 } 520 521 cmdbuf = obj_context->tng_cmdbuf_list[obj_context->cmdbuf_current]; 522 ret = tng_cmdbuf_reset(cmdbuf); 523 if (!ret) { 524 /* Success */ 525 obj_context->tng_cmdbuf = cmdbuf; 526 } 527 528 // tng_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->pic_params); 529 // tng_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->slice_mem); 530 return ret; 531 } 532 533 /* 534 * This is the user-space do-it-all interface to the drm cmdbuf ioctl. 535 * It allows different buffers as command- and reloc buffer. A list of 536 * cliprects to apply and whether to copy the clipRect content to all 537 * scanout buffers (damage = 1). 538 */ 539 /* 540 * Don't add debug statements in this function, it gets called with the 541 * DRM lock held and output to an X terminal can cause X to deadlock 542 */ 543 static int 544 ptgDRMCmdBuf(int fd, int ioctl_offset, psb_buffer_p *buffer_list, int buffer_count, unsigned cmdBufHandle, 545 unsigned cmdBufOffset, unsigned cmdBufSize, 546 unsigned relocBufHandle, unsigned relocBufOffset, 547 unsigned numRelocs, int __maybe_unused damage, 548 unsigned engine, unsigned fence_flags, struct psb_ttm_fence_rep *fence_rep) 549 { 550 drm_psb_cmdbuf_arg_t ca; 551 struct psb_validate_arg *arg_list; 552 int i, ret; 553 unsigned int retry = 0; 554 uint64_t mask = PSB_GPU_ACCESS_MASK; 555 556 arg_list = (struct psb_validate_arg *) calloc(1, sizeof(struct psb_validate_arg) * buffer_count); 557 if (arg_list == NULL) { 558 drv_debug_msg(VIDEO_DEBUG_ERROR, "Allocate memory failed\n"); 559 return -ENOMEM; 560 } 561 562 for (i = 0; i < buffer_count; i++) { 563 struct psb_validate_arg *arg = &(arg_list[i]); 564 struct psb_validate_req *req = &arg->d.req; 565 566 //memset(arg, 0, sizeof(*arg)); 567 req->next = (unsigned long) & (arg_list[i+1]); 568 569 req->buffer_handle = wsbmKBufHandle(wsbmKBuf(buffer_list[i]->drm_buf)); 570 //req->group = 0; 571 req->set_flags = (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE) & mask; 572 req->clear_flags = (~(PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)) & mask; 573 #if 1 574 req->presumed_gpu_offset = (uint64_t)wsbmBOOffsetHint(buffer_list[i]->drm_buf); 575 req->presumed_flags = PSB_USE_PRESUMED; 576 #else 577 req->presumed_flags = 0; 578 #endif 579 req->pad64 = (IMG_UINT32)buffer_list[i]->pl_flags; 580 #ifndef BAYTRAIL 581 req->unfence_flag = buffer_list[i]->unfence_flag; 582 #endif 583 } 584 arg_list[buffer_count-1].d.req.next = 0; 585 586 memset(&ca, 0, sizeof(ca)); 587 588 ca.buffer_list = (uint64_t)((unsigned long)arg_list); 589 ca.cmdbuf_handle = cmdBufHandle; 590 ca.cmdbuf_offset = cmdBufOffset; 591 ca.cmdbuf_size = cmdBufSize; 592 ca.reloc_handle = relocBufHandle; 593 ca.reloc_offset = relocBufOffset; 594 ca.num_relocs = numRelocs; 595 ca.engine = engine; 596 ca.fence_flags = fence_flags; 597 ca.fence_arg = (uint64_t)((unsigned long)fence_rep); 598 //ca.damage = damage; 599 600 601 do { 602 ret = drmCommandWrite(fd, ioctl_offset, &ca, sizeof(ca)); 603 if (ret == -EAGAIN || ret == -EBUSY) { 604 drv_debug_msg(VIDEO_DEBUG_ERROR, "drmCommandWrite returns with %s, retry\n", 605 ret==-EAGAIN?"EAGAIN":"EBUSY"); 606 retry++; 607 } 608 } while (ret == -EAGAIN || ret == -EBUSY); 609 610 if (retry > 0) 611 drv_debug_msg(VIDEO_DEBUG_ERROR,"drmCommandWrite tries %d time, finally %s with ret=%d\n", 612 retry, ret==0?"okay":"failed!", ret); 613 614 if (ret) 615 goto out; 616 617 for (i = 0; i < buffer_count; i++) { 618 struct psb_validate_arg *arg = &(arg_list[i]); 619 struct psb_validate_rep *rep = &arg->d.rep; 620 621 if (!arg->handled) { 622 ret = -EFAULT; 623 goto out; 624 } 625 if (arg->ret != 0) { 626 ret = arg->ret; 627 goto out; 628 } 629 wsbmUpdateKBuf(wsbmKBuf(buffer_list[i]->drm_buf), 630 rep->gpu_offset, rep->placement, rep->fence_type_mask); 631 } 632 out: 633 free(arg_list); 634 for (i = 0; i < buffer_count; i++) { 635 /* 636 * Buffer no longer queued in userspace 637 */ 638 switch (buffer_list[i]->status) { 639 case psb_bs_queued: 640 buffer_list[i]->status = psb_bs_ready; 641 break; 642 643 case psb_bs_abandoned: 644 psb_buffer_destroy(buffer_list[i]); 645 free(buffer_list[i]); 646 break; 647 648 default: 649 /* Not supposed to happen */ 650 ASSERT(0); 651 } 652 } 653 654 return ret; 655 } 656 657 #if 0 658 static struct _WsbmFenceObject * 659 lnc_fence_wait(psb_driver_data_p driver_data, 660 struct psb_ttm_fence_rep *fence_rep, int *status) 661 662 { 663 struct _WsbmFenceObject *fence = NULL; 664 int ret = -1; 665 666 /* copy fence information */ 667 if (fence_rep->error != 0) { 668 drv_debug_msg(VIDEO_DEBUG_ERROR, "drm failed to create a fence" 669 " and has idled the HW\n"); 670 DEBUG_FAILURE_RET; 671 return NULL; 672 } 673 674 fence = wsbmFenceCreate(driver_data->fence_mgr, fence_rep->fence_class, 675 fence_rep->fence_type, 676 (void *)fence_rep->handle, 677 0); 678 if (fence) 679 *status = wsbmFenceFinish(fence, fence_rep->fence_type, 0); 680 681 return fence; 682 } 683 #endif 684 685 /* 686 * Submits the current cmdbuf 687 * 688 * Returns 0 on success 689 */ 690 int tng_context_submit_cmdbuf(object_context_p __maybe_unused obj_context) 691 { 692 return 0; 693 } 694 695 696 697 /* 698 * FrameSkip is only meaningful for RC enabled mode 699 * Topaz raises this flag after surface N encoding is finished (vaSyncSurface gets back) 700 * then for the next encode surface N+1 (ctx->src_surface) frameskip flag is cleared in vaBeginPicuture 701 * and is always set in vaEndPicture:lnc_PatchRCMode 702 * vaQuerySurfaceStatus is supposed only to be called after vaEndPicture/vaSyncSurface, 703 * The caller should ensure the surface pertains to an encode context 704 */ 705 int tng_surface_get_frameskip(psb_driver_data_p __maybe_unused driver_data, 706 psb_surface_p surface, 707 int *frame_skip) 708 { 709 /* bit31 indicate if frameskip is already settled, it is used to record the frame skip flag for old surfaces 710 * bit31 is cleared when the surface is used as encode render target or reference/reconstrucure target 711 */ 712 if (GET_SURFACE_INFO_skipped_flag(surface) & SURFACE_INFO_SKIP_FLAG_SETTLED) { 713 *frame_skip = GET_SURFACE_INFO_skipped_flag(surface) & 1; 714 } else 715 *frame_skip = 0; 716 717 return 0; 718 } 719 720 VAStatus tng_set_frame_skip_flag(object_context_p obj_context) 721 { 722 VAStatus vaStatus = VA_STATUS_SUCCESS; 723 context_ENC_p ctx = (context_ENC_p) obj_context->format_data; 724 context_ENC_frame_buf *ps_buf = &(ctx->ctx_frame_buf); 725 726 if (ctx && ps_buf->previous_src_surface) { 727 SET_SURFACE_INFO_skipped_flag(ps_buf->previous_src_surface->psb_surface, 1); 728 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Detected a skipped frame for surface 0x%08x.\n", 729 ps_buf->previous_src_surface->psb_surface); 730 } 731 732 return vaStatus; 733 } 734 735 736 /* 737 * Flushes all cmdbufs 738 */ 739 int tng_context_flush_cmdbuf(object_context_p obj_context) 740 { 741 tng_cmdbuf_p cmdbuf = obj_context->tng_cmdbuf; 742 psb_driver_data_p driver_data = obj_context->driver_data; 743 unsigned int fence_flags; 744 struct psb_ttm_fence_rep fence_rep; 745 unsigned int reloc_offset; 746 unsigned int num_relocs; 747 int ret; 748 unsigned int cmdbuffer_size = (unsigned int) (((unsigned char *)(cmdbuf->cmd_idx)) - cmdbuf->cmd_start); /* In bytes */ 749 750 ASSERT(cmdbuffer_size < CMD_SIZE); 751 ASSERT((void *) cmdbuf->cmd_idx < CMD_END(cmdbuf)); 752 /* LOCK */ 753 ret = LOCK_HARDWARE(driver_data); 754 if (ret) { 755 UNLOCK_HARDWARE(driver_data); 756 DEBUG_FAILURE_RET; 757 return ret; 758 } 759 760 /* Now calculate the total number of relocations */ 761 reloc_offset = cmdbuf->reloc_base - cmdbuf->cmd_base; 762 num_relocs = (((unsigned char *) (cmdbuf->reloc_idx)) - cmdbuf->reloc_base) / sizeof(struct drm_psb_reloc); 763 764 tng_cmdbuf_unmap(cmdbuf); 765 766 ASSERT(NULL == cmdbuf->reloc_base); 767 768 #ifdef DEBUG_TRACE 769 fence_flags = 0; 770 #else 771 fence_flags = DRM_PSB_FENCE_NO_USER; 772 #endif 773 774 775 wsbmWriteLockKernelBO(); 776 #if 1 //_PO_DEBUG_ 777 ret = ptgDRMCmdBuf(driver_data->drm_fd, driver_data->execIoctlOffset, /* FIXME Still use ioctl cmd? */ 778 cmdbuf->buffer_refs, cmdbuf->buffer_refs_count, wsbmKBufHandle(wsbmKBuf(cmdbuf->buf.drm_buf)), 779 0, cmdbuffer_size,/*unsigned cmdBufSize*/ 780 wsbmKBufHandle(wsbmKBuf(cmdbuf->buf.drm_buf)), reloc_offset, num_relocs, 781 0, LNC_ENGINE_ENCODE, fence_flags, &fence_rep); /* FIXME use LNC_ENGINE_ENCODE */ 782 #endif 783 wsbmWriteUnlockKernelBO(); 784 785 UNLOCK_HARDWARE(driver_data); 786 787 if (ret) { 788 obj_context->tng_cmdbuf = NULL; 789 790 DEBUG_FAILURE_RET; 791 return ret; 792 } 793 794 #if 0 /*DEBUG_TRACE*/ 795 int status = -1; 796 struct _WsbmFenceObject *fence = NULL; 797 798 fence = lnc_fence_wait(driver_data, &fence_rep, &status); 799 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_fence_wait returns: %d (fence=0x%08x)\n", status, fence); 800 801 if (fence) 802 wsbmFenceUnreference(fence); 803 #endif 804 805 obj_context->tng_cmdbuf = NULL; 806 807 return 0; 808 } 809 810 811 void tng_cmdbuf_set_phys(IMG_UINT32 *dest_buf, int dest_num, 812 psb_buffer_p ref_buf, unsigned int ref_ofs, unsigned int ref_len) 813 { 814 int i = 0; 815 IMG_UINT32 addr_phys = (IMG_UINT32)wsbmBOOffsetHint(ref_buf->drm_buf) + ref_ofs; 816 817 // drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: drm_buf 0x%08x, addr_phys 0x%08x, virt addr 0x%08x\n", __FUNCTION__, ref_buf->drm_buf, addr_phys, ref_buf->virtual_addr ); 818 819 do { 820 dest_buf[i] = addr_phys; 821 ++i; 822 addr_phys += ref_len; 823 } while(i < dest_num); 824 return ; 825 } 826 827 828 int tng_get_pipe_number(object_context_p obj_context) 829 { 830 831 context_ENC_p ctx = (context_ENC_p)(obj_context->format_data); 832 return ctx->ui8PipesToUse; 833 834 } 835 836