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 * 28 */ 29 30 31 #include "psb_cmdbuf.h" 32 33 #include <unistd.h> 34 #include <stdio.h> 35 36 #include "hwdefs/mem_io.h" 37 #include "hwdefs/msvdx_offsets.h" 38 #include "hwdefs/dma_api.h" 39 #include "hwdefs/reg_io2.h" 40 #include "hwdefs/msvdx_vec_reg_io2.h" 41 #include "hwdefs/msvdx_vdmc_reg_io2.h" 42 #include "hwdefs/msvdx_mtx_reg_io2.h" 43 #include "hwdefs/msvdx_dmac_linked_list.h" 44 #include "hwdefs/msvdx_rendec_mtx_slice_cntrl_reg_io2.h" 45 #include "hwdefs/dxva_cmdseq_msg.h" 46 #include "hwdefs/dxva_fw_ctrl.h" 47 #include "hwdefs/fwrk_msg_mem_io.h" 48 #include "hwdefs/dxva_msg.h" 49 #include "hwdefs/msvdx_cmds_io2.h" 50 #include <stdlib.h> 51 #include <errno.h> 52 #include <string.h> 53 #include <sys/time.h> 54 55 #include "psb_def.h" 56 #include "psb_drv_debug.h" 57 #ifndef BAYTRAIL 58 #include "psb_ws_driver.h" 59 #endif 60 #include <wsbm/wsbm_pool.h> 61 #include <wsbm/wsbm_manager.h> 62 #include <wsbm/wsbm_util.h> 63 #include <wsbm/wsbm_fencemgr.h> 64 65 /* 66 * Buffer layout: 67 * cmd_base <= cmd_idx < CMD_END() == lldma_base 68 * lldma_base <= lldma_idx < LLDMA_END() == (cmd_base + size) 69 * 70 * Reloc buffer layout: 71 * MTX_msg < reloc_base == MTX_msg + MTXMSG_SIZE 72 * reloc_base <= reloc_idx < RELOC_END() == (MTX_msg + reloc_size) 73 */ 74 #define MTXMSG_END(cmdbuf) (cmdbuf->reloc_base) 75 #define RELOC_END(cmdbuf) (cmdbuf->MTX_msg + cmdbuf->reloc_size) 76 77 #define CMD_END(cmdbuf) (cmdbuf->lldma_base) 78 #define LLDMA_END(cmdbuf) (cmdbuf->cmd_base + cmdbuf->size) 79 80 #define MTXMSG_SIZE (0x1000) 81 #define RELOC_SIZE (0x3000) 82 83 #define CMD_SIZE (0x3000) 84 #define LLDMA_SIZE (0x2000) 85 86 #define MTXMSG_MARGIN (0x0040) 87 #define RELOC_MARGIN (0x0800) 88 89 #define CMD_MARGIN (0x0400) 90 #define LLDMA_MARGIN (0x0400) 91 #define PSB_SLICE_EXTRACT_UPDATE (0x2) 92 93 /* 94 * Create command buffer 95 */ 96 VAStatus psb_cmdbuf_create(object_context_p obj_context, psb_driver_data_p driver_data, 97 psb_cmdbuf_p cmdbuf 98 ) 99 { 100 VAStatus vaStatus = VA_STATUS_SUCCESS; 101 unsigned int size = CMD_SIZE + LLDMA_SIZE; 102 unsigned int reloc_size = MTXMSG_SIZE + RELOC_SIZE; 103 unsigned int regio_size = (obj_context->picture_width >> 4) * (obj_context->picture_height >> 4) * 172; 104 105 cmdbuf->size = 0; 106 cmdbuf->reloc_size = 0; 107 cmdbuf->regio_size = 0; 108 cmdbuf->MTX_msg = NULL; 109 cmdbuf->cmd_base = NULL; 110 cmdbuf->regio_base = NULL; 111 cmdbuf->cmd_idx = NULL; 112 cmdbuf->regio_idx = NULL; 113 cmdbuf->cmd_bitstream_size = NULL; 114 cmdbuf->lldma_base = NULL; 115 cmdbuf->lldma_idx = NULL; 116 cmdbuf->reloc_base = NULL; 117 cmdbuf->reloc_idx = NULL; 118 cmdbuf->reg_start = NULL; 119 cmdbuf->rendec_block_start = NULL; 120 cmdbuf->rendec_chunk_start = NULL; 121 cmdbuf->skip_block_start = NULL; 122 cmdbuf->last_next_segment_cmd = NULL; 123 cmdbuf->buffer_refs_count = 0; 124 cmdbuf->buffer_refs_allocated = 10; 125 cmdbuf->buffer_refs = (psb_buffer_p *) calloc(1, sizeof(psb_buffer_p) * cmdbuf->buffer_refs_allocated); 126 if (NULL == cmdbuf->buffer_refs) { 127 cmdbuf->buffer_refs_allocated = 0; 128 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 129 } 130 if (VA_STATUS_SUCCESS == vaStatus) { 131 vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_vpu, &cmdbuf->buf); 132 cmdbuf->size = size; 133 } 134 if (VA_STATUS_SUCCESS == vaStatus) { 135 vaStatus = psb_buffer_create(driver_data, reloc_size, psb_bt_cpu_only, &cmdbuf->reloc_buf); 136 cmdbuf->reloc_size = reloc_size; 137 } 138 if (VA_STATUS_SUCCESS == vaStatus) { 139 vaStatus = psb_buffer_create(driver_data, regio_size, psb_bt_cpu_only, &cmdbuf->regio_buf); 140 cmdbuf->regio_size = regio_size; 141 } 142 143 if (VA_STATUS_SUCCESS != vaStatus) { 144 psb_cmdbuf_destroy(cmdbuf); 145 } 146 return vaStatus; 147 } 148 149 /* 150 * Destroy buffer 151 */ 152 void psb_cmdbuf_destroy(psb_cmdbuf_p cmdbuf) 153 { 154 if (cmdbuf->size) { 155 psb_buffer_destroy(&cmdbuf->buf); 156 cmdbuf->size = 0; 157 } 158 if (cmdbuf->reloc_size) { 159 psb_buffer_destroy(&cmdbuf->reloc_buf); 160 cmdbuf->reloc_size = 0; 161 } 162 if (cmdbuf->regio_size) { 163 psb_buffer_destroy(&cmdbuf->regio_buf); 164 cmdbuf->regio_size = 0; 165 } 166 if (cmdbuf->buffer_refs_allocated) { 167 free(cmdbuf->buffer_refs); 168 cmdbuf->buffer_refs = NULL; 169 cmdbuf->buffer_refs_allocated = 0; 170 } 171 } 172 173 /* 174 * Reset buffer & map 175 * 176 * Returns 0 on success 177 */ 178 int psb_cmdbuf_reset(psb_cmdbuf_p cmdbuf) 179 { 180 int ret; 181 182 cmdbuf->MTX_msg = NULL; 183 cmdbuf->cmd_base = NULL; 184 cmdbuf->cmd_idx = NULL; 185 cmdbuf->cmd_bitstream_size = NULL; 186 cmdbuf->lldma_base = NULL; 187 cmdbuf->lldma_idx = NULL; 188 cmdbuf->reloc_base = NULL; 189 cmdbuf->reloc_idx = NULL; 190 cmdbuf->last_next_segment_cmd = NULL; 191 192 cmdbuf->buffer_refs_count = 0; 193 cmdbuf->cmd_count = 0; 194 cmdbuf->deblock_count = 0; 195 cmdbuf->oold_count = 0; 196 cmdbuf->host_be_opp_count = 0; 197 cmdbuf->frame_info_count = 0; 198 #ifdef SLICE_HEADER_PARSING 199 cmdbuf->parse_count = 0; 200 #endif 201 ret = psb_buffer_map(&cmdbuf->buf, &cmdbuf->cmd_base); 202 if (ret) { 203 return ret; 204 } 205 ret = psb_buffer_map(&cmdbuf->reloc_buf, &cmdbuf->MTX_msg); 206 if (ret) { 207 psb_buffer_unmap(&cmdbuf->buf); 208 return ret; 209 } 210 211 cmdbuf->cmd_start = cmdbuf->cmd_base; 212 cmdbuf->cmd_idx = (uint32_t *) cmdbuf->cmd_base; 213 cmdbuf->cmd_bitstream_size = NULL; 214 cmdbuf->lldma_base = cmdbuf->cmd_base + CMD_SIZE; 215 cmdbuf->lldma_idx = cmdbuf->lldma_base; 216 217 cmdbuf->reloc_base = cmdbuf->MTX_msg + MTXMSG_SIZE; 218 cmdbuf->reloc_idx = (struct drm_psb_reloc *) cmdbuf->reloc_base; 219 220 /* Add ourselves to the buffer list */ 221 psb_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->reloc_buf); /* reloc buf == 0 */ 222 psb_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->buf); /* cmd buf == 1 */ 223 return ret; 224 } 225 226 /* 227 * Unmap buffer 228 * 229 * Returns 0 on success 230 */ 231 int psb_cmdbuf_unmap(psb_cmdbuf_p cmdbuf) 232 { 233 cmdbuf->MTX_msg = NULL; 234 cmdbuf->cmd_base = NULL; 235 cmdbuf->cmd_start = NULL; 236 cmdbuf->cmd_idx = NULL; 237 cmdbuf->cmd_bitstream_size = NULL; 238 cmdbuf->lldma_base = NULL; 239 cmdbuf->lldma_idx = NULL; 240 cmdbuf->reloc_base = NULL; 241 cmdbuf->reloc_idx = NULL; 242 cmdbuf->cmd_count = 0; 243 psb_buffer_unmap(&cmdbuf->buf); 244 psb_buffer_unmap(&cmdbuf->reloc_buf); 245 return 0; 246 } 247 248 249 /* 250 * Reference an addtional buffer "buf" in the command stream 251 * Returns a reference index that can be used to refer to "buf" in 252 * relocation records, -1 on error 253 */ 254 int psb_cmdbuf_buffer_ref(psb_cmdbuf_p cmdbuf, psb_buffer_p buf) 255 { 256 int item_loc = 0; 257 258 // buf->next = NULL; /* buf->next only used for buffer list validation */ 259 while ((item_loc < cmdbuf->buffer_refs_count) 260 && (wsbmKBufHandle(wsbmKBuf(cmdbuf->buffer_refs[item_loc]->drm_buf)) 261 != wsbmKBufHandle(wsbmKBuf(buf->drm_buf)))) { 262 item_loc++; 263 } 264 if (item_loc == cmdbuf->buffer_refs_count) { 265 /* Add new entry */ 266 if (item_loc >= cmdbuf->buffer_refs_allocated) { 267 /* Allocate more entries */ 268 int new_size = cmdbuf->buffer_refs_allocated + 10; 269 psb_buffer_p *new_array; 270 new_array = (psb_buffer_p *) calloc(1, sizeof(psb_buffer_p) * new_size); 271 if (NULL == new_array) { 272 return -1; /* Allocation failure */ 273 } 274 memcpy(new_array, cmdbuf->buffer_refs, sizeof(psb_buffer_p) * cmdbuf->buffer_refs_allocated); 275 free(cmdbuf->buffer_refs); 276 cmdbuf->buffer_refs_allocated = new_size; 277 cmdbuf->buffer_refs = new_array; 278 } 279 cmdbuf->buffer_refs[item_loc] = buf; 280 cmdbuf->buffer_refs_count++; 281 buf->status = psb_bs_queued; 282 283 buf->next = NULL; 284 buf->unfence_flag = 0; 285 } 286 287 /* only for RAR buffers */ 288 if ((cmdbuf->buffer_refs[item_loc] != buf) 289 && (buf->rar_handle != 0)) { 290 psb_buffer_p tmp = cmdbuf->buffer_refs[item_loc]; 291 drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR: found same drm buffer with different psb buffer, link them\n", 292 tmp, buf); 293 while ((tmp->next != NULL)) { 294 tmp = tmp->next; 295 if (tmp == buf) /* found same buffer */ 296 break; 297 } 298 299 if (tmp != buf) { 300 tmp->next = buf; /* link it */ 301 buf->status = psb_bs_queued; 302 buf->next = NULL; 303 } else { 304 drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR: buffer aleady in the list, skip\n", 305 tmp, buf); 306 } 307 } 308 309 return item_loc; 310 } 311 312 /* Creates a relocation record for a DWORD in the mapped "cmdbuf" at address 313 * "addr_in_cmdbuf" 314 * The relocation is based on the device virtual address of "ref_buffer" 315 * "buf_offset" is be added to the device virtual address, and the sum is then 316 * right shifted with "align_shift". 317 * "mask" determines which bits of the target DWORD will be updated with the so 318 * constructed address. The remaining bits will be filled with bits from "background". 319 */ 320 void psb_cmdbuf_add_relocation(psb_cmdbuf_p cmdbuf, 321 uint32_t *addr_in_cmdbuf, 322 psb_buffer_p ref_buffer, 323 uint32_t buf_offset, 324 uint32_t mask, 325 uint32_t background, 326 uint32_t align_shift, 327 uint32_t dst_buffer) /* 0 = reloc buf, 1 = cmdbuf, 2 = for host reloc */ 328 { 329 struct drm_psb_reloc *reloc = cmdbuf->reloc_idx; 330 uint64_t presumed_offset = wsbmBOOffsetHint(ref_buffer->drm_buf); 331 332 /* Check that address is within buffer range */ 333 if (dst_buffer) { 334 ASSERT(((unsigned char *)(addr_in_cmdbuf)) >= cmdbuf->cmd_base); 335 ASSERT(((unsigned char *)(addr_in_cmdbuf)) < LLDMA_END(cmdbuf)); 336 reloc->where = addr_in_cmdbuf - (uint32_t *) cmdbuf->cmd_base; /* Location in DWORDs */ 337 } else { 338 ASSERT(((unsigned char *)(addr_in_cmdbuf)) >= cmdbuf->MTX_msg); 339 ASSERT(((unsigned char *)(addr_in_cmdbuf)) < MTXMSG_END(cmdbuf)); 340 reloc->where = addr_in_cmdbuf - (uint32_t *) cmdbuf->MTX_msg; /* Location in DWORDs */ 341 } 342 343 reloc->buffer = psb_cmdbuf_buffer_ref(cmdbuf, ref_buffer); 344 ASSERT(reloc->buffer != -1); 345 346 reloc->reloc_op = PSB_RELOC_OP_OFFSET; 347 348 psb__trace_message("[RE] Reloc at offset %08x (%08x), offset = %08x background = %08x buffer = %d (%08x)\n", 349 reloc->where, reloc->where << 2, buf_offset, background, reloc->buffer, presumed_offset); 350 351 if (presumed_offset) { 352 uint32_t new_val = presumed_offset + buf_offset; 353 new_val = ((new_val >> align_shift) << (align_shift << PSB_RELOC_ALSHIFT_SHIFT)); 354 new_val = (background & ~mask) | (new_val & mask); 355 *addr_in_cmdbuf = new_val; 356 } else { 357 *addr_in_cmdbuf = PSB_RELOC_MAGIC; 358 } 359 360 reloc->mask = mask; 361 reloc->shift = align_shift << PSB_RELOC_ALSHIFT_SHIFT; 362 reloc->pre_add = buf_offset; 363 reloc->background = background; 364 reloc->dst_buffer = dst_buffer; 365 cmdbuf->reloc_idx++; 366 367 ASSERT(((unsigned char *)(cmdbuf->reloc_idx)) < RELOC_END(cmdbuf)); 368 } 369 370 /* 371 * Advances "obj_context" to the next cmdbuf 372 * 373 * Returns 0 on success 374 */ 375 int psb_context_get_next_cmdbuf(object_context_p obj_context) 376 { 377 psb_cmdbuf_p cmdbuf; 378 int ret; 379 380 if (obj_context->cmdbuf) { 381 return 0; 382 } 383 384 obj_context->cmdbuf_current++; 385 if (obj_context->cmdbuf_current >= PSB_MAX_CMDBUFS) { 386 obj_context->cmdbuf_current = 0; 387 } 388 cmdbuf = obj_context->cmdbuf_list[obj_context->cmdbuf_current]; 389 ret = psb_cmdbuf_reset(cmdbuf); 390 if (!ret) { 391 /* Success */ 392 obj_context->cmdbuf = cmdbuf; 393 } 394 return ret; 395 } 396 397 398 static unsigned 399 psbTimeDiff(struct timeval *now, struct timeval *then) 400 { 401 long long val; 402 403 val = now->tv_sec - then->tv_sec; 404 val *= 1000000LL; 405 val += now->tv_usec; 406 val -= then->tv_usec; 407 if (val < 1LL) 408 val = 1LL; 409 410 return (unsigned) val; 411 } 412 413 /* 414 * This is the user-space do-it-all interface to the drm cmdbuf ioctl. 415 * It allows different buffers as command- and reloc buffer. A list of 416 * cliprects to apply and whether to copy the clipRect content to all 417 * scanout buffers (damage = 1). 418 */ 419 /* 420 * Don't add debug statements in this function, it gets called with the 421 * DRM lock held and output to an X terminal can cause X to deadlock 422 */ 423 static int 424 psbDRMCmdBuf(int fd, int ioctl_offset, psb_buffer_p *buffer_list, int buffer_count, unsigned cmdBufHandle, 425 unsigned cmdBufOffset, unsigned cmdBufSize, 426 unsigned relocBufHandle, unsigned relocBufOffset, 427 unsigned numRelocs, int __maybe_unused damage, 428 unsigned engine, unsigned fence_flags, struct psb_ttm_fence_rep *fence_arg) 429 { 430 drm_psb_cmdbuf_arg_t ca; 431 struct psb_validate_arg *arg_list; 432 int i; 433 int ret; 434 struct timeval then, now; 435 Bool have_then = FALSE; 436 uint64_t mask = PSB_GPU_ACCESS_MASK; 437 438 arg_list = (struct psb_validate_arg *) calloc(1, sizeof(struct psb_validate_arg) * buffer_count); 439 if (arg_list == NULL) { 440 drv_debug_msg(VIDEO_DEBUG_ERROR, "Malloc failed \n"); 441 return -ENOMEM; 442 } 443 444 for (i = 0; i < buffer_count; i++) { 445 struct psb_validate_arg *arg = &(arg_list[i]); 446 struct psb_validate_req *req = &arg->d.req; 447 448 req->next = (unsigned long) & (arg_list[i+1]); 449 450 req->buffer_handle = wsbmKBufHandle(wsbmKBuf(buffer_list[i]->drm_buf)); 451 //req->group = 0; 452 req->set_flags = (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE) & mask; 453 req->clear_flags = (~(PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)) & mask; 454 455 req->presumed_gpu_offset = (uint64_t)wsbmBOOffsetHint(buffer_list[i]->drm_buf); 456 req->presumed_flags = PSB_USE_PRESUMED; 457 req->pad64 = (uint32_t)buffer_list[i]->pl_flags; 458 #ifndef BAYTRAIL 459 req->unfence_flag = buffer_list[i]->unfence_flag; 460 #endif 461 } 462 arg_list[buffer_count-1].d.req.next = 0; 463 464 ca.buffer_list = (uint64_t)((unsigned long)arg_list); 465 ca.fence_arg = (uint64_t)((unsigned long)fence_arg); 466 467 ca.cmdbuf_handle = cmdBufHandle; 468 ca.cmdbuf_offset = cmdBufOffset; 469 ca.cmdbuf_size = cmdBufSize; 470 471 ca.reloc_handle = relocBufHandle; 472 ca.reloc_offset = relocBufOffset; 473 ca.num_relocs = numRelocs; 474 475 ca.fence_flags = fence_flags; 476 ca.engine = engine; 477 478 #if 0 479 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: buffer_list = %08x\n", ca.buffer_list); 480 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: clip_rects = %08x\n", ca.clip_rects); 481 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: cmdbuf_handle = %08x\n", ca.cmdbuf_handle); 482 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: cmdbuf_offset = %08x\n", ca.cmdbuf_offset); 483 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: cmdbuf_size = %08x\n", ca.cmdbuf_size); 484 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: reloc_handle = %08x\n", ca.reloc_handle); 485 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: reloc_offset = %08x\n", ca.reloc_offset); 486 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: num_relocs = %08x\n", ca.num_relocs); 487 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: engine = %08x\n", ca.engine); 488 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB submit: fence_flags = %08x\n", ca.fence_flags); 489 #endif 490 491 /* 492 * X server Signals will clobber the kernel time out mechanism. 493 * we need a user-space timeout as well. 494 */ 495 do { 496 ret = drmCommandWrite(fd, ioctl_offset, &ca, sizeof(ca)); 497 if (ret == EAGAIN) { 498 if (!have_then) { 499 if (gettimeofday(&then, NULL)) { 500 drv_debug_msg(VIDEO_DEBUG_ERROR, "Gettimeofday error.\n"); 501 break; 502 } 503 504 have_then = TRUE; 505 } 506 if (gettimeofday(&now, NULL)) { 507 drv_debug_msg(VIDEO_DEBUG_ERROR, "Gettimeofday error.\n"); 508 break; 509 } 510 511 } 512 } while ((ret == EAGAIN) && (psbTimeDiff(&now, &then) < PSB_TIMEOUT_USEC)); 513 514 if (ret) { 515 drv_debug_msg(VIDEO_DEBUG_GENERAL, "command write return is %d\n", ret); 516 goto out; 517 } 518 519 for (i = 0; i < buffer_count; i++) { 520 struct psb_validate_arg *arg = &(arg_list[i]); 521 struct psb_validate_rep *rep = &arg->d.rep; 522 523 #ifndef BAYTRAIL 524 if (arg->d.req.unfence_flag) 525 continue; 526 #endif 527 528 if (!arg->handled) { 529 ret = -EFAULT; 530 goto out; 531 } 532 if (arg->ret != 0) { 533 ret = arg->ret; 534 goto out; 535 } 536 wsbmUpdateKBuf(wsbmKBuf(buffer_list[i]->drm_buf), 537 rep->gpu_offset, rep->placement, rep->fence_type_mask); 538 } 539 540 out: 541 free(arg_list); 542 for (i = 0; i < buffer_count; i++) { 543 /* 544 * Buffer no longer queued in userspace 545 */ 546 psb_buffer_p tmp = buffer_list[i]; 547 548 /* 549 * RAR slice buffer/surface buffer are share one BO, and then only one in 550 * buffer_list, but they are linked in psb_cmdbuf_buffer_ref 551 552 */ 553 if (buffer_list[i]->rar_handle == 0) 554 tmp->next = NULL; /* don't loop for non RAR buffer, "next" may be not initialized */ 555 556 do { 557 psb_buffer_p p = tmp; 558 559 tmp = tmp->next; 560 switch (p->status) { 561 case psb_bs_queued: 562 p->status = psb_bs_ready; 563 break; 564 565 case psb_bs_abandoned: 566 psb_buffer_destroy(p); 567 free(p); 568 break; 569 570 default: 571 /* Not supposed to happen */ 572 ASSERT(0); 573 } 574 } while (tmp); 575 } 576 577 return ret; 578 } 579 580 #if 0 581 int psb_fence_destroy(struct _WsbmFenceObject *pFence) 582 { 583 wsbmFenceUnreference(&pFence); 584 585 return 0; 586 } 587 588 struct _WsbmFenceObject * 589 psb_fence_wait(psb_driver_data_p driver_data, 590 struct psb_ttm_fence_rep *fence_rep, int *status) 591 592 { 593 struct _WsbmFenceObject *fence = NULL; 594 int ret = -1; 595 596 /* copy fence information */ 597 if (fence_rep->error != 0) { 598 drv_debug_msg(VIDEO_DEBUG_ERROR, "drm failed to create a fence" 599 " and has idled the HW\n"); 600 DEBUG_FAILURE_RET; 601 return NULL; 602 } 603 604 fence = wsbmFenceCreate(driver_data->fence_mgr, fence_rep->fence_class, 605 fence_rep->fence_type, 606 (unsigned char *)fence_rep->handle, 607 0); 608 if (fence) 609 *status = wsbmFenceFinish(fence, fence_rep->fence_type, 0); 610 611 return fence; 612 } 613 #endif 614 615 /* 616 * Closes the last segment 617 */ 618 static void psb_cmdbuf_close_segment(psb_cmdbuf_p __maybe_unused cmdbuf) 619 { 620 #if 0 621 uint32_t bytes_used = ((unsigned char *) cmdbuf->cmd_idx - cmdbuf->cmd_start) % MTX_SEG_SIZE; 622 unsigned char *segment_start = (unsigned char *) cmdbuf->cmd_idx - bytes_used; 623 uint32_t lldma_record_offset = psb_cmdbuf_lldma_create(cmdbuf, 624 &(cmdbuf->buf), (segment_start - cmdbuf->cmd_base) /* offset */, 625 bytes_used, 626 0 /* destination offset */, 627 LLDMA_TYPE_RENDER_BUFF_MC); 628 uint32_t cmd = CMD_NEXT_SEG; 629 RELOC_SHIFT4(*cmdbuf->last_next_segment_cmd, lldma_record_offset, cmd, &(cmdbuf->buf)); 630 *(cmdbuf->last_next_segment_cmd + 1) = bytes_used; 631 #endif 632 } 633 634 /* Issue deblock cmd, HW will do deblock instead of host */ 635 int psb_context_submit_hw_deblock(object_context_p obj_context, 636 psb_buffer_p buf_a, 637 psb_buffer_p buf_b, 638 psb_buffer_p colocate_buffer, 639 uint32_t picture_widht_mb, 640 uint32_t frame_height_mb, 641 uint32_t rotation_flags, 642 uint32_t field_type, 643 uint32_t ext_stride_a, 644 uint32_t chroma_offset_a, 645 uint32_t chroma_offset_b, 646 uint32_t is_oold) 647 { 648 psb_cmdbuf_p cmdbuf = obj_context->cmdbuf; 649 psb_driver_data_p driver_data = obj_context->driver_data; 650 uint32_t msg_size = FW_DEVA_DEBLOCK_SIZE; 651 unsigned int item_size = FW_DEVA_DECODE_SIZE; /* Size of a render/deocde msg */ 652 FW_VA_DEBLOCK_MSG *deblock_msg; 653 654 uint32_t *msg = (uint32_t *)(cmdbuf->MTX_msg + item_size * cmdbuf->cmd_count); 655 656 memset(msg, 0, sizeof(FW_VA_DEBLOCK_MSG)); 657 deblock_msg = (FW_VA_DEBLOCK_MSG *)msg; 658 659 deblock_msg->header.bits.msg_size = FW_DEVA_DEBLOCK_SIZE; 660 if (is_oold) 661 deblock_msg->header.bits.msg_type = VA_MSGID_OOLD_MFLD; 662 else 663 deblock_msg->header.bits.msg_type = VA_MSGID_DEBLOCK_MFLD; 664 deblock_msg->flags.bits.flags = FW_VA_RENDER_HOST_INT | FW_VA_RENDER_IS_LAST_SLICE | FW_DEVA_DEBLOCK_ENABLE; 665 deblock_msg->flags.bits.slice_type = field_type; 666 deblock_msg->operating_mode = obj_context->operating_mode; 667 deblock_msg->mmu_context.bits.context = (uint8_t)(obj_context->msvdx_context); 668 deblock_msg->pic_size.bits.frame_height_mb = (uint16_t)frame_height_mb; 669 deblock_msg->pic_size.bits.pic_width_mb = (uint16_t)picture_widht_mb; 670 deblock_msg->ext_stride_a = ext_stride_a; 671 deblock_msg->rotation_flags = rotation_flags; 672 673 RELOC_MSG(deblock_msg->address_a0, buf_a->buffer_ofs, buf_a); 674 RELOC_MSG(deblock_msg->address_a1, buf_a->buffer_ofs + chroma_offset_a, buf_a); 675 if (buf_b) { 676 RELOC_MSG(deblock_msg->address_b0, buf_b->buffer_ofs, buf_b); 677 RELOC_MSG(deblock_msg->address_b1, buf_b->buffer_ofs + chroma_offset_b, buf_b); 678 } 679 680 RELOC_MSG(deblock_msg->mb_param_address, colocate_buffer->buffer_ofs, colocate_buffer); 681 cmdbuf->deblock_count++; 682 return 0; 683 } 684 685 #ifdef PSBVIDEO_MSVDX_EC 686 int psb_context_submit_host_be_opp(object_context_p obj_context, 687 psb_buffer_p buf_a, 688 psb_buffer_p buf_b, 689 psb_buffer_p __maybe_unused buf_c, 690 uint32_t picture_widht_mb, 691 uint32_t frame_height_mb, 692 uint32_t rotation_flags, 693 uint32_t field_type, 694 uint32_t ext_stride_a, 695 uint32_t chroma_offset_a, 696 uint32_t chroma_offset_b) 697 { 698 psb_cmdbuf_p cmdbuf = obj_context->cmdbuf; 699 psb_driver_data_p driver_data = obj_context->driver_data; 700 uint32_t msg_size = sizeof(FW_VA_DEBLOCK_MSG); 701 unsigned int item_size = FW_DEVA_DECODE_SIZE; /* Size of a render/deocde msg */ 702 FW_VA_DEBLOCK_MSG *deblock_msg; 703 704 uint32_t *msg = (uint32_t *)(cmdbuf->MTX_msg + item_size * cmdbuf->cmd_count + cmdbuf->deblock_count * msg_size); 705 706 memset(msg, 0, sizeof(FW_VA_DEBLOCK_MSG)); 707 deblock_msg = (FW_VA_DEBLOCK_MSG *)msg; 708 709 deblock_msg->header.bits.msg_size = FW_DEVA_DEBLOCK_SIZE; 710 deblock_msg->header.bits.msg_type = VA_MSGID_HOST_BE_OPP_MFLD; 711 deblock_msg->flags.bits.flags = FW_VA_RENDER_HOST_INT | FW_ERROR_DETECTION_AND_RECOVERY; 712 deblock_msg->flags.bits.slice_type = field_type; 713 deblock_msg->operating_mode = obj_context->operating_mode; 714 deblock_msg->mmu_context.bits.context = (uint8_t)(obj_context->msvdx_context); 715 deblock_msg->pic_size.bits.frame_height_mb = (uint16_t)frame_height_mb; 716 deblock_msg->pic_size.bits.pic_width_mb = (uint16_t)picture_widht_mb; 717 deblock_msg->ext_stride_a = ext_stride_a; 718 deblock_msg->rotation_flags = rotation_flags; 719 720 RELOC_MSG(deblock_msg->address_a0, buf_a->buffer_ofs, buf_a); 721 RELOC_MSG(deblock_msg->address_a1, buf_a->buffer_ofs + chroma_offset_a, buf_a); 722 RELOC_MSG(deblock_msg->address_b0, buf_b->buffer_ofs, buf_b); 723 RELOC_MSG(deblock_msg->address_b1, buf_b->buffer_ofs + chroma_offset_b, buf_b); 724 725 deblock_msg->mb_param_address = wsbmKBufHandle(wsbmKBuf(buf_a->drm_buf)); 726 cmdbuf->deblock_count++; 727 return 0; 728 } 729 #endif 730 /* 731 * Submits the current cmdbuf 732 * 733 * Returns 0 on success 734 */ 735 int psb_context_submit_cmdbuf(object_context_p obj_context) 736 { 737 psb_cmdbuf_p cmdbuf = obj_context->cmdbuf; 738 psb_driver_data_p driver_data = obj_context->driver_data; 739 unsigned int item_size = FW_DEVA_DECODE_SIZE; /* Size of a render/deocde msg */ 740 int ret; 741 742 743 uint32_t cmdbuffer_size = (unsigned char *) cmdbuf->cmd_idx - cmdbuf->cmd_start; // In bytes 744 745 if (cmdbuf->last_next_segment_cmd) { 746 cmdbuffer_size = cmdbuf->first_segment_size; 747 psb_cmdbuf_close_segment(cmdbuf); 748 } 749 750 uint32_t msg_size = item_size; 751 uint32_t *msg = (uint32_t *)(cmdbuf->MTX_msg + cmdbuf->cmd_count * msg_size + cmdbuf->frame_info_count * FW_VA_FRAME_INFO_SIZE); 752 753 if (psb_video_trace_fp && (psb_video_trace_level & CMDMSG_TRACE)) { 754 debug_cmd_start[cmdbuf->cmd_count] = cmdbuf->cmd_start - cmdbuf->cmd_base; 755 debug_cmd_size[cmdbuf->cmd_count] = (unsigned char *) cmdbuf->cmd_idx - cmdbuf->cmd_start; 756 debug_cmd_count = cmdbuf->cmd_count + 1; 757 } 758 759 /* 760 static int c = 0; 761 static char pFileName[30]; 762 763 764 sprintf(pFileName , "cmdbuf%i.txt", c++); 765 FILE* pF = fopen(pFileName, "w"); 766 767 fwrite(cmdbuf->cmd_start, 1, cmdbuffer_size, pF); 768 fclose(pF); 769 */ 770 ret = psb_cmdbuf_dump((unsigned int *)cmdbuf->cmd_start, cmdbuffer_size); 771 if(ret) 772 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_cmdbuf: dump cmdbuf fail\n"); 773 774 cmdbuf->cmd_count++; 775 memset(msg, 0, msg_size); 776 777 *cmdbuf->cmd_idx = 0; // Add a trailing 0 just in case. 778 ASSERT(cmdbuffer_size < CMD_SIZE); 779 ASSERT((unsigned char *) cmdbuf->cmd_idx < CMD_END(cmdbuf)); 780 781 MEMIO_WRITE_FIELD(msg, FWRK_GENMSG_SIZE, msg_size); 782 MEMIO_WRITE_FIELD(msg, FWRK_GENMSG_ID, VA_MSGID_RENDER); 783 784 MEMIO_WRITE_FIELD(msg, FW_DEVA_DECODE_CONTEXT, (obj_context->msvdx_context)); /* context is 8 bits */ 785 786 /* Point to CMDBUFFER */ 787 RELOC_MSG(*(msg + (FW_DEVA_DECODE_LLDMA_ADDRESS_OFFSET / sizeof(uint32_t))), 788 (cmdbuf->cmd_start - cmdbuf->cmd_base), &(cmdbuf->buf)); 789 MEMIO_WRITE_FIELD(msg, FW_DEVA_DECODE_BUFFER_SIZE, cmdbuffer_size / 4); // In dwords 790 MEMIO_WRITE_FIELD(msg, FW_DEVA_DECODE_OPERATING_MODE, obj_context->operating_mode); 791 MEMIO_WRITE_FIELD(msg, FW_DEVA_DECODE_FLAGS, obj_context->flags); 792 793 if (psb_video_trace_fp && (psb_video_trace_level & LLDMA_TRACE)) { 794 debug_lldma_count = (cmdbuf->lldma_idx - cmdbuf->lldma_base) / sizeof(DMA_sLinkedList); 795 debug_lldma_start = cmdbuf->lldma_base - cmdbuf->cmd_base; 796 /* Indicate last LLDMA record (for debugging) */ 797 ((uint32_t *)cmdbuf->lldma_idx)[1] = 0; 798 } 799 800 cmdbuf->cmd_start = (unsigned char *)cmdbuf->cmd_idx; 801 802 if (psb_video_trace_fp) { 803 return psb_context_flush_cmdbuf(obj_context); 804 } else { 805 if ((cmdbuf->cmd_count >= MAX_CMD_COUNT) || 806 (MTXMSG_END(cmdbuf) - (unsigned char *) msg < MTXMSG_MARGIN) || 807 (CMD_END(cmdbuf) - (unsigned char *) cmdbuf->cmd_idx < CMD_MARGIN) || 808 (LLDMA_END(cmdbuf) - cmdbuf->lldma_idx < LLDMA_MARGIN) || 809 (RELOC_END(cmdbuf) - (unsigned char *) cmdbuf->reloc_idx < RELOC_MARGIN)) { 810 return psb_context_flush_cmdbuf(obj_context); 811 } 812 } 813 return 0; 814 } 815 816 /* 817 * Flushes all cmdbufs 818 */ 819 int psb_context_flush_cmdbuf(object_context_p obj_context) 820 { 821 psb_cmdbuf_p cmdbuf = obj_context->cmdbuf; 822 psb_driver_data_p driver_data = obj_context->driver_data; 823 unsigned int fence_flags; 824 /* unsigned int fence_handle = 0; */ 825 struct psb_ttm_fence_rep fence_rep; 826 unsigned int reloc_offset; 827 unsigned int num_relocs; 828 int ret; 829 unsigned int item_size = FW_DEVA_DECODE_SIZE; /* Size of a render/deocde msg */ 830 831 #ifdef SLICE_HEADER_PARSING 832 if ((NULL == cmdbuf) || 833 (0 == (cmdbuf->cmd_count + cmdbuf->deblock_count + cmdbuf->host_be_opp_count + 834 cmdbuf->frame_info_count + cmdbuf->parse_count))) { 835 return 0; // Nothing to do 836 } 837 #else 838 if ((NULL == cmdbuf) || 839 (0 == (cmdbuf->cmd_count + cmdbuf->deblock_count + cmdbuf->host_be_opp_count + cmdbuf->frame_info_count))) { 840 return 0; // Nothing to do 841 } 842 #endif 843 844 uint32_t msg_size = 0; 845 uint32_t *msg = (uint32_t *)cmdbuf->MTX_msg; 846 int32_t i; 847 uint32_t index; 848 849 /* LOCK */ 850 ret = LOCK_HARDWARE(driver_data); 851 if (ret) { 852 UNLOCK_HARDWARE(driver_data); 853 DEBUG_FAILURE_RET; 854 return ret; 855 } 856 857 for (i = 1; i <= cmdbuf->frame_info_count; i++) { 858 msg_size += FW_VA_FRAME_INFO_SIZE; 859 msg += FW_VA_FRAME_INFO_SIZE / sizeof(uint32_t); 860 } 861 862 for (i = 1; i <= cmdbuf->cmd_count; i++) { 863 uint32_t flags; 864 865 flags = MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_FLAGS); 866 867 /* Update flags */ 868 int bBatchEnd = (i == (cmdbuf->cmd_count + cmdbuf->deblock_count + cmdbuf->oold_count 869 + cmdbuf->host_be_opp_count)); 870 flags |= 871 (bBatchEnd ? FW_VA_RENDER_HOST_INT : FW_VA_RENDER_NO_RESPONCE_MSG); 872 873 #ifdef PSBVIDEO_MSVDX_EC 874 if (driver_data->ec_enabled) 875 flags |= FW_ERROR_DETECTION_AND_RECOVERY; 876 #endif 877 878 MEMIO_WRITE_FIELD(msg, FW_DEVA_DECODE_FLAGS, flags); 879 880 psb__trace_message("MSG BUFFER_SIZE = %08x\n", MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_BUFFER_SIZE)); 881 psb__trace_message("MSG OPERATING_MODE = %08x\n", MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_OPERATING_MODE)); 882 psb__trace_message("MSG FLAGS = %08x\n", MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_FLAGS)); 883 884 drv_debug_msg(VIDEO_DEBUG_GENERAL, "MSG BUFFER_SIZE = %08x\n", MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_BUFFER_SIZE)); 885 drv_debug_msg(VIDEO_DEBUG_GENERAL, "MSG OPERATING_MODE = %08x\n", MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_OPERATING_MODE)); 886 drv_debug_msg(VIDEO_DEBUG_GENERAL, "MSG FLAGS = %08x\n", MEMIO_READ_FIELD(msg, FW_DEVA_DECODE_FLAGS)); 887 888 #if 0 /* todo */ 889 /* Update SAREA */ 890 driver_data->psb_sarea->msvdx_context = obj_context->msvdx_context; 891 #endif 892 msg += item_size / sizeof(uint32_t); 893 msg_size += item_size; 894 } 895 896 /* Assume deblock message is following render messages and no more render message behand deblock message */ 897 for (i = 1; i <= cmdbuf->deblock_count; i++) { 898 msg_size += sizeof(FW_VA_DEBLOCK_MSG); 899 } 900 901 for (i = 1; i <= cmdbuf->oold_count; i++) { 902 msg_size += sizeof(FW_VA_DEBLOCK_MSG); 903 } 904 905 for (i = 1; i <= cmdbuf->host_be_opp_count; i++) { 906 msg_size += FW_VA_HOST_BE_OPP_SIZE; 907 } 908 #ifdef SLICE_HEADER_PARSING 909 for (i = 1; i <= cmdbuf->parse_count; i++) { 910 msg_size += sizeof(struct fw_slice_header_extract_msg); 911 } 912 #endif 913 /* Now calculate the total number of relocations */ 914 reloc_offset = cmdbuf->reloc_base - cmdbuf->MTX_msg; 915 num_relocs = (((unsigned char *) cmdbuf->reloc_idx) - cmdbuf->reloc_base) / sizeof(struct drm_psb_reloc); 916 917 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Cmdbuf MTXMSG size = %08x [%08x]\n", msg_size, MTXMSG_SIZE); 918 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Cmdbuf CMD size = %08x - %d[%08x]\n", (unsigned char *) cmdbuf->cmd_idx - cmdbuf->cmd_base, cmdbuf->cmd_count, CMD_SIZE); 919 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Cmdbuf LLDMA size = %08x [%08x]\n", cmdbuf->lldma_idx - cmdbuf->lldma_base, LLDMA_SIZE); 920 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Cmdbuf RELOC size = %08x [%08x]\n", num_relocs * sizeof(struct drm_psb_reloc), RELOC_SIZE); 921 922 psb_cmdbuf_unmap(cmdbuf); 923 924 psb__trace_message(NULL); /* Flush trace */ 925 926 ASSERT(NULL == cmdbuf->MTX_msg); 927 ASSERT(NULL == cmdbuf->reloc_base); 928 929 if (psb_video_trace_fp) 930 fence_flags = 0; 931 else 932 fence_flags = DRM_PSB_FENCE_NO_USER; 933 934 #ifdef SLICE_HEADER_PARSING 935 if (obj_context->msvdx_frame_end) 936 fence_flags |= PSB_SLICE_EXTRACT_UPDATE; 937 #endif 938 /* cmdbuf will be validated as part of the buffer list */ 939 /* Submit */ 940 wsbmWriteLockKernelBO(); 941 ret = psbDRMCmdBuf(driver_data->drm_fd, driver_data->execIoctlOffset, cmdbuf->buffer_refs, 942 cmdbuf->buffer_refs_count, 943 wsbmKBufHandle(wsbmKBuf(cmdbuf->reloc_buf.drm_buf)), 944 0, msg_size, 945 wsbmKBufHandle(wsbmKBuf(cmdbuf->reloc_buf.drm_buf)), 946 reloc_offset, num_relocs, 947 0, PSB_ENGINE_DECODE, fence_flags, &fence_rep); 948 wsbmWriteUnlockKernelBO(); 949 UNLOCK_HARDWARE(driver_data); 950 951 if (ret) { 952 obj_context->cmdbuf = NULL; 953 obj_context->slice_count++; 954 955 DEBUG_FAILURE_RET; 956 return ret; 957 } 958 959 if (psb_video_trace_fp) { 960 #if 0 961 static int error_count = 0; 962 int status = 0; 963 struct _WsbmFenceObject *fence = NULL; 964 fence = psb_fence_wait(driver_data, &fence_rep, &status); 965 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_fence_wait returns: %d (fence=0x%08x)\n", status, fence); 966 #endif 967 968 psb_buffer_map(&cmdbuf->buf, &cmdbuf->cmd_base); 969 int ret; 970 ret = psb_buffer_map(&cmdbuf->reloc_buf, &cmdbuf->MTX_msg); 971 if(ret) { 972 psb_buffer_unmap(&cmdbuf->buf); 973 return ret; 974 } 975 976 if (psb_video_trace_level & LLDMA_TRACE) { 977 psb__trace_message("lldma_count = %d, vitual=0x%08x\n", 978 debug_lldma_count, wsbmBOOffsetHint(cmdbuf->buf.drm_buf) + CMD_SIZE); 979 for (index = 0; index < debug_lldma_count; index++) { 980 DMA_sLinkedList* pasDmaList = (DMA_sLinkedList*)(cmdbuf->cmd_base + debug_lldma_start); 981 pasDmaList += index; 982 983 psb__trace_message("\nLLDMA record at offset %08x\n", ((unsigned char*)pasDmaList) - cmdbuf->cmd_base); 984 DW(0, BSWAP, 31, 31) 985 DW(0, DIR, 30, 30) 986 DW(0, PW, 29, 28) 987 DW(1, List_FIN, 31, 31) 988 DW(1, List_INT, 30, 30) 989 DW(1, PI, 18, 17) 990 DW(1, INCR, 16, 16) 991 DW(1, LEN, 15, 0) 992 DWH(2, ADDR, 22, 0) 993 DW(3, ACC_DEL, 31, 29) 994 DW(3, BURST, 28, 26) 995 DWH(3, EXT_SA, 3, 0) 996 DW(4, 2D_MODE, 16, 16) 997 DW(4, REP_COUNT, 10, 0) 998 DWH(5, LINE_ADD_OFF, 25, 16) 999 DW(5, ROW_LENGTH, 9, 0) 1000 DWH(6, SA, 31, 0) 1001 DWH(7, LISTPTR, 27, 0) 1002 } 1003 } 1004 1005 if (psb_video_trace_level & AUXBUF_TRACE) { 1006 psb__trace_message("debug_dump_count = %d\n", debug_dump_count); 1007 for (index = 0; index < debug_dump_count; index++) { 1008 unsigned char *buf_addr; 1009 psb__trace_message("Buffer %d = '%s' offset = %08x size = %08x\n", index, debug_dump_name[index], debug_dump_offset[index], debug_dump_size[index]); 1010 if (debug_dump_buf[index]->rar_handle 1011 || (psb_buffer_map(debug_dump_buf[index], &buf_addr) != 0)) { 1012 psb__trace_message("Unmappable buffer,e.g. RAR buffer\n"); 1013 continue; 1014 } 1015 1016 g_hexdump_offset = 0; 1017 psb__hexdump(buf_addr + debug_dump_offset[index], debug_dump_size[index]); 1018 psb_buffer_unmap(debug_dump_buf[index]); 1019 } 1020 debug_dump_count = 0; 1021 } 1022 1023 if (psb_video_trace_level & CMDMSG_TRACE) { 1024 psb__trace_message("cmd_count = %d, virtual=0x%08x\n", 1025 debug_cmd_count, wsbmBOOffsetHint(cmdbuf->buf.drm_buf)); 1026 for (index = 0; index < debug_cmd_count; index++) { 1027 uint32_t *msg = (uint32_t *)(cmdbuf->MTX_msg + index * item_size); 1028 uint32_t j; 1029 drv_debug_msg(VIDEO_DEBUG_GENERAL, "start = %08x size = %08x\n", debug_cmd_start[index], debug_cmd_size[index]); 1030 debug_dump_cmdbuf((uint32_t *)(cmdbuf->cmd_base + debug_cmd_start[index]), debug_cmd_size[index]); 1031 1032 for (j = 0; j < item_size / 4; j++) { 1033 psb__trace_message("MTX msg[%d] = 0x%08x", j, *(msg + j)); 1034 switch (j) { 1035 case 0: 1036 psb__trace_message("[BufferSize|ID|MSG_SIZE]\n"); 1037 break; 1038 case 1: 1039 psb__trace_message("[MMUPTD]\n"); 1040 break; 1041 case 2: 1042 psb__trace_message("[LLDMA_address]\n"); 1043 break; 1044 case 3: 1045 psb__trace_message("[Context]\n"); 1046 break; 1047 case 4: 1048 psb__trace_message("[Fence_Value]\n"); 1049 break; 1050 case 5: 1051 psb__trace_message("[Operating_Mode]\n"); 1052 break; 1053 case 6: 1054 psb__trace_message("[LastMB|FirstMB]\n"); 1055 break; 1056 case 7: 1057 psb__trace_message("[Flags]\n"); 1058 break; 1059 default: 1060 psb__trace_message("[overflow]\n"); 1061 break; 1062 } 1063 } 1064 } 1065 debug_cmd_count = 0; 1066 } 1067 psb_buffer_unmap(&cmdbuf->buf); 1068 psb_buffer_unmap(&cmdbuf->reloc_buf); 1069 1070 cmdbuf->cmd_base = NULL; 1071 #if 0 1072 if (status) { 1073 drv_debug_msg(VIDEO_DEBUG_ERROR, "RENDERING ERROR FRAME=%03d SLICE=%02d status=%d\n", obj_context->frame_count, obj_context->slice_count, status); 1074 error_count++; 1075 ASSERT(status != 2); 1076 ASSERT(error_count < 40); /* Exit on 40 errors */ 1077 } 1078 if (fence) 1079 psb_fence_destroy(fence); 1080 #endif 1081 } 1082 1083 obj_context->cmdbuf = NULL; 1084 obj_context->slice_count++; 1085 1086 return 0; 1087 } 1088 1089 1090 typedef enum { 1091 MMU_GROUP0 = 0, 1092 MMU_GROUP1 = 1, 1093 } MMU_GROUP; 1094 1095 typedef enum { 1096 HOST_TO_MSVDX = 0, 1097 MSXDX_TO_HOST = 1, 1098 } DMA_DIRECTION; 1099 1100 typedef struct { 1101 IMG_UINT32 ui32DevDestAddr ; /* destination address */ 1102 DMA_ePW ePeripheralWidth; 1103 DMA_ePeriphIncrSize ePeriphIncrSize; 1104 DMA_ePeriphIncr ePeriphIncr; 1105 IMG_BOOL bSynchronous; 1106 MMU_GROUP eMMUGroup; 1107 DMA_DIRECTION eDMADir; 1108 DMA_eBurst eDMA_eBurst; 1109 } DMA_DETAIL_LOOKUP; 1110 1111 1112 static const DMA_DETAIL_LOOKUP DmaDetailLookUp[] = { 1113 /* LLDMA_TYPE_VLC_TABLE */ { 1114 REG_MSVDX_VEC_VLC_OFFSET , 1115 DMA_PWIDTH_16_BIT, /* 16 bit wide data*/ 1116 DMA_PERIPH_INCR_4, /* Incrament the dest by 32 bits */ 1117 DMA_PERIPH_INCR_ON, 1118 IMG_TRUE, 1119 MMU_GROUP0, 1120 HOST_TO_MSVDX, 1121 DMA_BURST_2 1122 }, 1123 /* LLDMA_TYPE_BITSTREAM */ { 1124 (REG_MSVDX_VEC_OFFSET + MSVDX_VEC_CR_VEC_SHIFTREG_STREAMIN_OFFSET), 1125 DMA_PWIDTH_8_BIT, 1126 DMA_PERIPH_INCR_1, 1127 DMA_PERIPH_INCR_OFF, 1128 IMG_FALSE, 1129 MMU_GROUP0, 1130 HOST_TO_MSVDX, 1131 DMA_BURST_4 1132 }, 1133 /*LLDMA_TYPE_RESIDUAL*/ { 1134 (REG_MSVDX_VDMC_OFFSET + MSVDX_VDMC_CR_VDMC_RESIDUAL_DIRECT_INSERT_DATA_OFFSET), 1135 DMA_PWIDTH_32_BIT, 1136 DMA_PERIPH_INCR_1, 1137 DMA_PERIPH_INCR_OFF, 1138 IMG_FALSE, 1139 MMU_GROUP1, 1140 HOST_TO_MSVDX, 1141 DMA_BURST_4 1142 }, 1143 1144 /*LLDMA_TYPE_RENDER_BUFF_MC*/{ 1145 (REG_MSVDX_MTX_OFFSET + MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET), 1146 DMA_PWIDTH_32_BIT, 1147 DMA_PERIPH_INCR_1, 1148 DMA_PERIPH_INCR_OFF, 1149 IMG_TRUE, 1150 MMU_GROUP1, 1151 HOST_TO_MSVDX, 1152 DMA_BURST_1 /* Into MTX */ 1153 }, 1154 /*LLDMA_TYPE_RENDER_BUFF_VLD*/{ 1155 (REG_MSVDX_MTX_OFFSET + MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET), 1156 DMA_PWIDTH_32_BIT, 1157 DMA_PERIPH_INCR_1, 1158 DMA_PERIPH_INCR_OFF, 1159 IMG_TRUE, 1160 MMU_GROUP0, 1161 HOST_TO_MSVDX, 1162 DMA_BURST_1 /* Into MTX */ 1163 }, 1164 /*LLDMA_TYPE_MPEG4_FESTATE_SAVE*/{ 1165 (REG_MSVDX_VEC_RAM_OFFSET + 0xB90), 1166 DMA_PWIDTH_32_BIT, 1167 DMA_PERIPH_INCR_4, 1168 DMA_PERIPH_INCR_ON, 1169 IMG_TRUE, 1170 MMU_GROUP0, 1171 MSXDX_TO_HOST, 1172 DMA_BURST_2 /* From VLR */ 1173 }, 1174 /*LLDMA_TYPE_MPEG4_FESTATE_RESTORE*/{ 1175 (REG_MSVDX_VEC_RAM_OFFSET + 0xB90), 1176 DMA_PWIDTH_32_BIT, 1177 DMA_PERIPH_INCR_4, 1178 DMA_PERIPH_INCR_ON, 1179 IMG_TRUE, 1180 MMU_GROUP0, 1181 HOST_TO_MSVDX, 1182 DMA_BURST_2 /* Into VLR */ 1183 }, 1184 /*LLDMA_TYPE_H264_PRELOAD_SAVE*/{ 1185 (REG_MSVDX_MTX_OFFSET + MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET), 1186 DMA_PWIDTH_32_BIT, 1187 DMA_PERIPH_INCR_1, 1188 DMA_PERIPH_INCR_OFF, 1189 IMG_TRUE, /* na */ 1190 MMU_GROUP1, 1191 MSXDX_TO_HOST, 1192 DMA_BURST_1 /* From MTX */ 1193 }, 1194 /*LLDMA_TYPE_H264_PRELOAD_RESTORE*/{ 1195 (REG_MSVDX_MTX_OFFSET + MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET), 1196 DMA_PWIDTH_32_BIT, 1197 DMA_PERIPH_INCR_1, 1198 DMA_PERIPH_INCR_OFF, 1199 IMG_TRUE, /* na */ 1200 MMU_GROUP1, 1201 HOST_TO_MSVDX, 1202 DMA_BURST_1 /* Into MTX */ 1203 }, 1204 /*LLDMA_TYPE_VC1_PRELOAD_SAVE*/{ 1205 (REG_MSVDX_MTX_OFFSET + MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET), 1206 DMA_PWIDTH_32_BIT, 1207 DMA_PERIPH_INCR_1, 1208 DMA_PERIPH_INCR_OFF, 1209 IMG_TRUE, /* na */ 1210 MMU_GROUP0, 1211 MSXDX_TO_HOST, 1212 DMA_BURST_1 //2 /* From MTX */ 1213 }, 1214 /*LLDMA_TYPE_VC1_PRELOAD_RESTORE*/{ 1215 (REG_MSVDX_MTX_OFFSET + MTX_CORE_CR_MTX_SYSC_CDMAT_OFFSET), 1216 DMA_PWIDTH_32_BIT, 1217 DMA_PERIPH_INCR_1, 1218 DMA_PERIPH_INCR_OFF, 1219 IMG_TRUE, /* na */ 1220 MMU_GROUP0, 1221 HOST_TO_MSVDX, 1222 DMA_BURST_1 /* Into MTX */ 1223 }, 1224 /*LLDMA_TYPE_MEM_SET */{ 1225 (REG_MSVDX_VEC_RAM_OFFSET + 0xCC0), 1226 DMA_PWIDTH_32_BIT, 1227 DMA_PERIPH_INCR_4, 1228 DMA_PERIPH_INCR_OFF, 1229 IMG_TRUE, /* na */ 1230 MMU_GROUP0, 1231 MSXDX_TO_HOST, 1232 DMA_BURST_4 /* From VLR */ 1233 }, 1234 1235 }; 1236 1237 #define MAX_DMA_LEN ( 0xffff ) 1238 1239 void *psb_cmdbuf_alloc_space(psb_cmdbuf_p cmdbuf, uint32_t byte_size) 1240 { 1241 void *pos = (void *)cmdbuf->cmd_idx; 1242 ASSERT(!(byte_size % 4)); 1243 1244 cmdbuf->cmd_idx += (byte_size / 4); 1245 1246 return pos; 1247 } 1248 1249 void psb_cmdbuf_dma_write_cmdbuf(psb_cmdbuf_p cmdbuf, 1250 psb_buffer_p bitstream_buf, 1251 uint32_t buffer_offset, 1252 uint32_t size, 1253 uint32_t dest_offset, 1254 DMA_TYPE type) 1255 { 1256 ASSERT(size < 0xFFFF); 1257 ASSERT(buffer_offset < 0xFFFF); 1258 1259 DMA_CMD_WITH_OFFSET* dma_cmd; 1260 1261 if(dest_offset==0) 1262 { 1263 dma_cmd = (DMA_CMD_WITH_OFFSET*)psb_cmdbuf_alloc_space(cmdbuf, sizeof(DMA_CMD)); 1264 dma_cmd->ui32Cmd = 0; 1265 } 1266 else 1267 { 1268 dma_cmd = (DMA_CMD_WITH_OFFSET*)psb_cmdbuf_alloc_space(cmdbuf, sizeof(DMA_CMD_WITH_OFFSET)); 1269 dma_cmd->ui32Cmd = CMD_DMA_OFFSET_FLAG; // Set flag indicating that offset is deffined 1270 dma_cmd->ui32ByteOffset = dest_offset; 1271 } 1272 1273 dma_cmd->ui32Cmd |= CMD_DMA; 1274 dma_cmd->ui32Cmd |= (IMG_UINT32)type; 1275 dma_cmd->ui32Cmd |= size; 1276 /* dma_cmd->ui32DevVirtAdd = ui32DevVirtAddress; */ 1277 RELOC(dma_cmd->ui32DevVirtAdd, buffer_offset, bitstream_buf); 1278 } 1279 1280 /* 1281 * Write a CMD_SR_SETUP referencing a bitstream buffer to the command buffer 1282 */ 1283 void psb_cmdbuf_dma_write_bitstream(psb_cmdbuf_p cmdbuf, 1284 psb_buffer_p bitstream_buf, 1285 uint32_t buffer_offset, 1286 uint32_t size_in_bytes, 1287 uint32_t offset_in_bits, 1288 uint32_t flags) 1289 { 1290 /* 1291 * We use byte alignment instead of 32bit alignment. 1292 * The third frame of sa10164.vc1 results in the following bitstream 1293 * patttern: 1294 * [0000] 00 00 03 01 76 dc 04 8d 1295 * with offset_in_bits = 0x1e 1296 * This causes an ENTDEC failure because 00 00 03 is a start code 1297 * By byte aligning the datastream the start code will be eliminated. 1298 */ 1299 //don't need to change the offset_in_bits, size_in_bytes and buffer_offset 1300 #if 0 1301 #define ALIGNMENT sizeof(uint8_t) 1302 uint32_t bs_offset_in_dwords = ((offset_in_bits / 8) / ALIGNMENT); 1303 size_in_bytes -= bs_offset_in_dwords * ALIGNMENT; 1304 offset_in_bits -= bs_offset_in_dwords * 8 * ALIGNMENT; 1305 buffer_offset += bs_offset_in_dwords * ALIGNMENT; 1306 #endif 1307 1308 *cmdbuf->cmd_idx++ = CMD_SR_SETUP | flags; 1309 *cmdbuf->cmd_idx++ = offset_in_bits; 1310 cmdbuf->cmd_bitstream_size = cmdbuf->cmd_idx; 1311 *cmdbuf->cmd_idx++ = size_in_bytes; 1312 *cmdbuf->cmd_idx++ = (CMD_BITSTREAM_DMA | size_in_bytes); 1313 RELOC(*cmdbuf->cmd_idx++, buffer_offset, bitstream_buf); 1314 } 1315 1316 #ifdef SLICE_HEADER_PARSING 1317 /* 1318 * Write a CMD_SR_SETUP referencing a bitstream buffer to the command buffer 1319 */ 1320 void psb_cmdbuf_dma_write_key(psb_cmdbuf_p cmdbuf, 1321 uint32_t flags, 1322 uint32_t key) 1323 { 1324 drv_debug_msg(VIDEO_DEBUG_GENERAL, "pass key, flags is 0x%x, key is 0x%x.\n", flags, key); 1325 *cmdbuf->cmd_idx++ = CMD_SR_SETUP | flags; 1326 *cmdbuf->cmd_idx++ = key; 1327 } 1328 #endif 1329 1330 /* 1331 * Chain a LLDMA bitstream command to the previous one 1332 */ 1333 void psb_cmdbuf_dma_write_bitstream_chained(psb_cmdbuf_p cmdbuf, 1334 psb_buffer_p bitstream_buf, 1335 uint32_t size_in_bytes) 1336 { 1337 *cmdbuf->cmd_idx++ = (CMD_BITSTREAM_DMA | size_in_bytes); 1338 RELOC(*cmdbuf->cmd_idx++, bitstream_buf->buffer_ofs, bitstream_buf); 1339 1340 *(cmdbuf->cmd_bitstream_size) += size_in_bytes; 1341 } 1342 1343 void psb_cmdbuf_reg_start_block(psb_cmdbuf_p cmdbuf, uint32_t flags) 1344 { 1345 ASSERT(NULL == cmdbuf->reg_start); /* Can't have both */ 1346 1347 cmdbuf->reg_wt_p = cmdbuf->cmd_idx; 1348 cmdbuf->reg_next = 0; 1349 cmdbuf->reg_flags = (flags << 4); /* flags are diff between DE2 & DE3 */ 1350 cmdbuf->reg_start = NULL; 1351 } 1352 1353 void psb_cmdbuf_reg_set(psb_cmdbuf_p cmdbuf, uint32_t reg, uint32_t val) 1354 { 1355 if(cmdbuf->reg_start && (reg == cmdbuf->reg_next)) 1356 { 1357 /* Incrament header size */ 1358 *cmdbuf->reg_start += (0x1 << 16); 1359 } 1360 else 1361 { 1362 cmdbuf->reg_start = cmdbuf->reg_wt_p++; 1363 *cmdbuf->reg_start = CMD_REGVALPAIR_WRITE | cmdbuf->reg_flags | 0x10000 | (reg & 0xfffff); /* We want host reg addr */ 1364 } 1365 *cmdbuf->reg_wt_p++ = val; 1366 cmdbuf->reg_next = reg + 4; 1367 } 1368 1369 void psb_cmdbuf_reg_set_address(psb_cmdbuf_p cmdbuf, 1370 uint32_t reg, 1371 psb_buffer_p buffer, 1372 uint32_t buffer_offset) 1373 { 1374 if(cmdbuf->reg_start && (reg == cmdbuf->reg_next)) 1375 { 1376 /* Incrament header size */ 1377 *cmdbuf->reg_start += (0x1 << 16); 1378 } 1379 else 1380 { 1381 cmdbuf->reg_start = cmdbuf->reg_wt_p++; 1382 *cmdbuf->reg_start = CMD_REGVALPAIR_WRITE | cmdbuf->reg_flags | 0x10000 | (reg & 0xfffff); /* We want host reg addr */ 1383 } 1384 1385 RELOC(*cmdbuf->reg_wt_p++, buffer_offset, buffer); 1386 cmdbuf->reg_next = reg + 4; 1387 } 1388 1389 void psb_cmdbuf_reg_end_block(psb_cmdbuf_p cmdbuf) 1390 { 1391 cmdbuf->cmd_idx = cmdbuf->reg_wt_p; 1392 cmdbuf->reg_start = NULL; 1393 } 1394 1395 typedef enum { 1396 MTX_CTRL_HEADER = 0, 1397 RENDEC_SL_HDR, 1398 RENDEC_SL_NULL, 1399 RENDEC_CK_HDR, 1400 } RENDEC_CHUNK_OFFSETS; 1401 1402 /* 1403 * Start a new rendec block of another format 1404 */ 1405 void psb_cmdbuf_rendec_start(psb_cmdbuf_p cmdbuf, uint32_t dest_address) 1406 { 1407 ASSERT(((dest_address >> 2)& ~0xfff) == 0); 1408 cmdbuf->rendec_chunk_start = cmdbuf->cmd_idx++; 1409 *cmdbuf->rendec_chunk_start = CMD_RENDEC_BLOCK | dest_address; 1410 } 1411 1412 void psb_cmdbuf_rendec_write_block(psb_cmdbuf_p cmdbuf, 1413 unsigned char *block, 1414 uint32_t size) 1415 { 1416 ASSERT((size & 0x3) == 0); 1417 unsigned int i; 1418 for (i = 0; i < size; i += 4) { 1419 uint32_t val = block[i] | (block[i+1] << 8) | (block[i+2] << 16) | (block[i+3] << 24); 1420 psb_cmdbuf_rendec_write(cmdbuf, val); 1421 } 1422 } 1423 1424 void psb_cmdbuf_rendec_write_address(psb_cmdbuf_p cmdbuf, 1425 psb_buffer_p buffer, 1426 uint32_t buffer_offset) 1427 { 1428 RELOC(*cmdbuf->cmd_idx++, buffer_offset, buffer); 1429 } 1430 1431 /* 1432 * Finish a RENDEC block 1433 */ 1434 void psb_cmdbuf_rendec_end(psb_cmdbuf_p cmdbuf) 1435 { 1436 ASSERT(NULL != cmdbuf->rendec_chunk_start); /* Must have an open RENDEC chunk */ 1437 uint32_t dword_count = cmdbuf->cmd_idx - cmdbuf->rendec_chunk_start; 1438 1439 ASSERT((dword_count - 1) <= 0xff); 1440 1441 *cmdbuf->rendec_chunk_start += ((dword_count - 1) << 16); 1442 cmdbuf->rendec_chunk_start = NULL; 1443 } 1444 1445 /* 1446 * Create a conditional SKIP block 1447 */ 1448 void psb_cmdbuf_skip_start_block(psb_cmdbuf_p cmdbuf, uint32_t skip_condition) 1449 { 1450 ASSERT(NULL == cmdbuf->rendec_block_start); /* Can't be inside a rendec block */ 1451 ASSERT(NULL == cmdbuf->reg_start); /* Can't be inside a reg block */ 1452 ASSERT(NULL == cmdbuf->skip_block_start); /* Can't be inside another skip block (limitation of current sw design)*/ 1453 1454 cmdbuf->skip_condition = skip_condition; 1455 cmdbuf->skip_block_start = cmdbuf->cmd_idx++; 1456 } 1457 1458 /* 1459 * Terminate a conditional SKIP block 1460 */ 1461 void psb_cmdbuf_skip_end_block(psb_cmdbuf_p cmdbuf) 1462 { 1463 ASSERT(NULL == cmdbuf->rendec_block_start); /* Rendec block must be closed */ 1464 ASSERT(NULL == cmdbuf->reg_start); /* Reg block must be closed */ 1465 ASSERT(NULL != cmdbuf->skip_block_start); /* Skip block must still be open */ 1466 1467 uint32_t block_size = cmdbuf->cmd_idx - (cmdbuf->skip_block_start + 1); 1468 1469 *cmdbuf->skip_block_start = CMD_CONDITIONAL_SKIP | (cmdbuf->skip_condition << 20) | block_size; 1470 cmdbuf->skip_block_start = NULL; 1471 } 1472