Home | History | Annotate | Download | only in src
      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  *
     29  */
     30 
     31 
     32 #include "pnw_cmdbuf.h"
     33 
     34 #include <unistd.h>
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <errno.h>
     38 #include <string.h>
     39 #include <wsbm/wsbm_manager.h>
     40 
     41 #include "psb_def.h"
     42 #include "psb_drv_debug.h"
     43 #include "pnw_hostcode.h"
     44 #include "psb_ws_driver.h"
     45 
     46 /*
     47  * Buffer layout:
     48  *         cmd_base <= cmd_idx < CMD_END() == reloc_base
     49  *         reloc_base <= reloc_idx < RELOC_END() == (reloc_size)
     50  */
     51 
     52 #define RELOC_END(cmdbuf)     (cmdbuf->cmd_base + cmdbuf->size)
     53 
     54 #define CMD_END(cmdbuf)       (cmdbuf->reloc_base)
     55 
     56 #define RELOC_SIZE            (0x3000)
     57 
     58 #define CMD_SIZE              (0x3000)
     59 
     60 #define RELOC_MARGIN          (0x0800)
     61 
     62 #define CMD_MARGIN            (0x0400)
     63 
     64 
     65 #define MAX_CMD_COUNT         12
     66 
     67 #define MTX_SEG_SIZE          (0x0800)
     68 
     69 
     70 /*
     71  * Create command buffer
     72  */
     73 VAStatus pnw_cmdbuf_create(
     74     object_context_p obj_context,
     75     psb_driver_data_p driver_data,
     76     pnw_cmdbuf_p cmdbuf)
     77 {
     78     context_ENC_p ctx = (context_ENC_p) obj_context->format_data;
     79     VAStatus vaStatus = VA_STATUS_SUCCESS;
     80     unsigned int size = CMD_SIZE + RELOC_SIZE;
     81 
     82     cmdbuf->size = 0;
     83     cmdbuf->cmd_base = NULL;
     84     cmdbuf->cmd_idx = NULL;
     85     cmdbuf->reloc_base = NULL;
     86     cmdbuf->reloc_idx = NULL;
     87     cmdbuf->buffer_refs_count = 0;
     88     cmdbuf->buffer_refs_allocated = 10;
     89     cmdbuf->buffer_refs = (psb_buffer_p *) calloc(1, sizeof(psb_buffer_p) * cmdbuf->buffer_refs_allocated);
     90     if (NULL == cmdbuf->buffer_refs) {
     91         cmdbuf->buffer_refs_allocated = 0;
     92         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
     93     }
     94     if (VA_STATUS_SUCCESS == vaStatus) {
     95         vaStatus = psb_buffer_create(driver_data, size, psb_bt_cpu_only, &cmdbuf->buf);
     96         cmdbuf->size = size;
     97     }
     98 
     99     if (VA_STATUS_SUCCESS != vaStatus) {
    100         free(cmdbuf->buffer_refs);
    101         cmdbuf->buffer_refs = NULL;
    102         cmdbuf->buffer_refs_allocated = 0;
    103         return vaStatus;
    104     }
    105 
    106     /* create topaz parameter buffer */
    107     vaStatus = psb_buffer_create(driver_data, ctx->pic_params_size * MAX_TOPAZ_CORES, psb_bt_cpu_vpu, &cmdbuf->pic_params);
    108     if (VA_STATUS_SUCCESS != vaStatus)
    109         goto error_out5;
    110 
    111     /* create header buffer */
    112     vaStatus = psb_buffer_create(driver_data, ctx->header_buffer_size, psb_bt_cpu_vpu, &cmdbuf->header_mem);
    113     if (VA_STATUS_SUCCESS != vaStatus)
    114         goto error_out2;
    115 
    116     /* create slice parameter buffer */
    117     vaStatus = psb_buffer_create(driver_data, ctx->sliceparam_buffer_size, psb_bt_cpu_vpu, &cmdbuf->slice_params);
    118     if (VA_STATUS_SUCCESS != vaStatus)
    119         goto error_out1;
    120 
    121     /* all cmdbuf share one MTX_CURRENT_IN_PARAMS since every MB has a MTX_CURRENT_IN_PARAMS structure
    122      * and filling this structure for all MB is very time-consuming
    123      */
    124 
    125     cmdbuf->topaz_in_params_I = &ctx->topaz_in_params_I;
    126     cmdbuf->topaz_in_params_P = &ctx->topaz_in_params_P;
    127 
    128     cmdbuf->topaz_below_params = &ctx->topaz_below_params;
    129     cmdbuf->topaz_above_params = &ctx->topaz_above_params;
    130 
    131     return vaStatus;
    132 
    133 error_out1:
    134     psb_buffer_destroy(&cmdbuf->header_mem);
    135 error_out2:
    136     psb_buffer_destroy(&cmdbuf->pic_params);
    137 error_out5:
    138     pnw_cmdbuf_destroy(cmdbuf);
    139 
    140     return vaStatus;
    141 }
    142 
    143 /*
    144  * Destroy buffer
    145  */
    146 void pnw_cmdbuf_destroy(pnw_cmdbuf_p cmdbuf)
    147 {
    148     if (cmdbuf->size) {
    149         psb_buffer_destroy(&cmdbuf->buf);
    150         cmdbuf->size = 0;
    151     }
    152     if (cmdbuf->buffer_refs_allocated) {
    153         free(cmdbuf->buffer_refs);
    154         cmdbuf->buffer_refs = NULL;
    155         cmdbuf->buffer_refs_allocated = 0;
    156     }
    157 
    158     psb_buffer_destroy(&cmdbuf->pic_params);
    159     psb_buffer_destroy(&cmdbuf->header_mem);
    160     psb_buffer_destroy(&cmdbuf->slice_params);
    161 
    162 }
    163 
    164 /*
    165  * Reset buffer & map
    166  *
    167  * Returns 0 on success
    168  */
    169 int pnw_cmdbuf_reset(pnw_cmdbuf_p cmdbuf)
    170 {
    171     int ret;
    172 
    173     cmdbuf->cmd_base = NULL;
    174     cmdbuf->cmd_idx = NULL;
    175     cmdbuf->reloc_base = NULL;
    176     cmdbuf->reloc_idx = NULL;
    177 
    178     cmdbuf->buffer_refs_count = 0;
    179     cmdbuf->cmd_count = 0;
    180 
    181     ret = psb_buffer_map(&cmdbuf->buf, &cmdbuf->cmd_base);
    182     if (ret) {
    183         return ret;
    184     }
    185 
    186     cmdbuf->cmd_start = cmdbuf->cmd_base;
    187     cmdbuf->cmd_idx = (uint32_t *) cmdbuf->cmd_base;
    188 
    189     cmdbuf->reloc_base = cmdbuf->cmd_base + CMD_SIZE;
    190     cmdbuf->reloc_idx = (struct drm_psb_reloc *) cmdbuf->reloc_base;
    191 
    192     /* Add ourselves to the buffer list */
    193     pnw_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->buf); /* cmd buf == 0 */
    194     return ret;
    195 }
    196 
    197 /*
    198  * Unmap buffer
    199  *
    200  * Returns 0 on success
    201  */
    202 int pnw_cmdbuf_unmap(pnw_cmdbuf_p cmdbuf)
    203 {
    204     cmdbuf->cmd_base = NULL;
    205     cmdbuf->cmd_start = NULL;
    206     cmdbuf->cmd_idx = NULL;
    207     cmdbuf->reloc_base = NULL;
    208     cmdbuf->reloc_idx = NULL;
    209     cmdbuf->cmd_count = 0;
    210     psb_buffer_unmap(&cmdbuf->buf);
    211     return 0;
    212 }
    213 
    214 
    215 /*
    216  * Reference an addtional buffer "buf" in the command stream
    217  * Returns a reference index that can be used to refer to "buf" in
    218  * relocation records, -1 on error
    219  */
    220 int pnw_cmdbuf_buffer_ref(pnw_cmdbuf_p cmdbuf, psb_buffer_p buf)
    221 {
    222     int item_loc = 0;
    223 
    224     /*Reserve the same TTM BO twice will cause kernel lock up*/
    225     while ((item_loc < cmdbuf->buffer_refs_count)
    226            && (wsbmKBufHandle(wsbmKBuf(cmdbuf->buffer_refs[item_loc]->drm_buf))
    227                != wsbmKBufHandle(wsbmKBuf(buf->drm_buf))))
    228         //while( (item_loc < cmdbuf->buffer_refs_count) && (cmdbuf->buffer_refs[item_loc] != buf) )
    229     {
    230         item_loc++;
    231     }
    232     if (item_loc == cmdbuf->buffer_refs_count) {
    233         /* Add new entry */
    234         if (item_loc >= cmdbuf->buffer_refs_allocated) {
    235             /* Allocate more entries */
    236             int new_size = cmdbuf->buffer_refs_allocated + 10;
    237             psb_buffer_p *new_array;
    238             new_array = (psb_buffer_p *) calloc(1, sizeof(psb_buffer_p) * new_size);
    239             if (NULL == new_array) {
    240                 return -1; /* Allocation failure */
    241             }
    242             memcpy(new_array, cmdbuf->buffer_refs, sizeof(psb_buffer_p) * cmdbuf->buffer_refs_allocated);
    243             free(cmdbuf->buffer_refs);
    244             cmdbuf->buffer_refs_allocated = new_size;
    245             cmdbuf->buffer_refs = new_array;
    246         }
    247         cmdbuf->buffer_refs[item_loc] = buf;
    248         cmdbuf->buffer_refs_count++;
    249         buf->status = psb_bs_queued;
    250     }
    251     return item_loc;
    252 }
    253 
    254 /* Creates a relocation record for a DWORD in the mapped "cmdbuf" at address
    255  * "addr_in_cmdbuf"
    256  * The relocation is based on the device virtual address of "ref_buffer"
    257  * "buf_offset" is be added to the device virtual address, and the sum is then
    258  * right shifted with "align_shift".
    259  * "mask" determines which bits of the target DWORD will be updated with the so
    260  * constructed address. The remaining bits will be filled with bits from "background".
    261  */
    262 void pnw_cmdbuf_add_relocation(pnw_cmdbuf_p cmdbuf,
    263                                uint32_t *addr_in_dst_buffer,/*addr of dst_buffer for the DWORD*/
    264                                psb_buffer_p ref_buffer,
    265                                uint32_t buf_offset,
    266                                uint32_t mask,
    267                                uint32_t background,
    268                                uint32_t align_shift,
    269                                uint32_t dst_buffer,
    270                                uint32_t *start_of_dst_buffer) /*Index of the list refered by cmdbuf->buffer_refs */
    271 {
    272     struct drm_psb_reloc *reloc = cmdbuf->reloc_idx;
    273     uint64_t presumed_offset = wsbmBOOffsetHint(ref_buffer->drm_buf);
    274 
    275     reloc->where = addr_in_dst_buffer - start_of_dst_buffer; /* Offset in DWORDs */
    276 
    277     reloc->buffer = pnw_cmdbuf_buffer_ref(cmdbuf, ref_buffer);
    278     ASSERT(reloc->buffer != -1);
    279 
    280     reloc->reloc_op = PSB_RELOC_OP_OFFSET;
    281 #ifndef VA_EMULATOR
    282     if (presumed_offset) {
    283         uint32_t new_val =  presumed_offset + buf_offset;
    284 
    285         new_val = ((new_val >> align_shift) << (align_shift << PSB_RELOC_ALSHIFT_SHIFT));
    286         new_val = (background & ~mask) | (new_val & mask);
    287         *addr_in_dst_buffer = new_val;
    288     } else {
    289         *addr_in_dst_buffer = PSB_RELOC_MAGIC;
    290     }
    291 #else
    292     /* indicate subscript of relocation buffer */
    293     *addr_in_dst_buffer = reloc - (struct drm_psb_reloc *)cmdbuf->reloc_base;
    294 #endif
    295     reloc->mask = mask;
    296     reloc->shift = align_shift << PSB_RELOC_ALSHIFT_SHIFT;
    297     reloc->pre_add = buf_offset;
    298     reloc->background = background;
    299     reloc->dst_buffer = dst_buffer;
    300     cmdbuf->reloc_idx++;
    301 
    302     ASSERT(((unsigned char *)(cmdbuf->reloc_idx)) < RELOC_END(cmdbuf));
    303 }
    304 
    305 /* Prepare one command package */
    306 void pnw_cmdbuf_insert_command_package(object_context_p obj_context,
    307                                        int32_t core,
    308                                        uint32_t cmd_id,
    309                                        psb_buffer_p command_data,
    310                                        uint32_t offset)
    311 {
    312     uint32_t cmd_word;
    313     context_ENC_p ctx = (context_ENC_p) obj_context->format_data;
    314     pnw_cmdbuf_p cmdbuf = obj_context->pnw_cmdbuf;
    315     int interrupt_flags;
    316 
    317     /* only MTX_CMDID_END_PIC by master core generate interrupt */
    318     interrupt_flags = (cmd_id == MTX_CMDID_END_PIC) | (core == 0);
    319     interrupt_flags = 0; /*CMD composed by user space does not generate Interrupt*/
    320 
    321     /* Calculate command word */
    322     cmd_id &= MTX_CMDWORD_ID_MASK;
    323     core &= MTX_CMDWORD_CORE_MASK;
    324 
    325     core %= MAX_TOPAZ_CORES;
    326 
    327     cmd_word = ((ctx->CmdCount & MTX_CMDWORD_COUNT_MASK) << MTX_CMDWORD_COUNT_SHIFT)
    328                | ((0 & MTX_CMDWORD_INT_MASK) << MTX_CMDWORD_INT_SHIFT) /* Do not generate interrupt */
    329                | (core << MTX_CMDWORD_CORE_SHIFT)
    330                | (cmd_id << MTX_CMDWORD_ID_SHIFT);
    331 
    332     /* write command word into cmdbuf */
    333     *cmdbuf->cmd_idx++ = cmd_word;
    334 
    335     /* Command data address */
    336     if (command_data) {
    337         RELOC_CMDBUF_PNW(cmdbuf->cmd_idx, offset, command_data);
    338         cmdbuf->cmd_idx++;
    339     } else {
    340         *cmdbuf->cmd_idx++ = 0;
    341     }
    342 
    343 
    344     *cmdbuf->cmd_idx++ = 0;             /* Write back buffer address */
    345 
    346     *cmdbuf->cmd_idx++ = 0; /*ctx->CmdCount; */ /* Write back value */
    347 
    348     ctx->LastSync[(ctx->FrmIdx) & 0x1][core] = ctx->CmdCount;
    349 
    350     /* increment the command counter */
    351     ctx->CmdCount = (ctx->CmdCount + 1) % MAX_TOPAZ_CMD_COUNT;
    352 }
    353 
    354 /*
    355  * Advances "obj_context" to the next cmdbuf
    356  *
    357  * Returns 0 on success
    358  */
    359 int pnw_context_get_next_cmdbuf(object_context_p obj_context)
    360 {
    361     pnw_cmdbuf_p cmdbuf;
    362     int ret;
    363 
    364     if (obj_context->pnw_cmdbuf) {
    365         return 0;
    366     }
    367 
    368     obj_context->cmdbuf_current++;
    369     if (obj_context->cmdbuf_current >= PNW_MAX_CMDBUFS_ENCODE) {
    370         obj_context->cmdbuf_current = 0;
    371     }
    372 
    373     cmdbuf = obj_context->pnw_cmdbuf_list[obj_context->cmdbuf_current];
    374     ret = pnw_cmdbuf_reset(cmdbuf);
    375     if (!ret) {
    376         /* Success */
    377         obj_context->pnw_cmdbuf = cmdbuf;
    378     }
    379 
    380     /* added pic_params/slice_params into ref, so the index is 1/2 */
    381     pnw_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->pic_params);
    382     pnw_cmdbuf_buffer_ref(cmdbuf, &cmdbuf->slice_params);
    383 
    384     return ret;
    385 }
    386 
    387 /*
    388  * This is the user-space do-it-all interface to the drm cmdbuf ioctl.
    389  * It allows different buffers as command- and reloc buffer. A list of
    390  * cliprects to apply and whether to copy the clipRect content to all
    391  * scanout buffers (damage = 1).
    392  */
    393 /*
    394  * Don't add debug statements in this function, it gets called with the
    395  * DRM lock held and output to an X terminal can cause X to deadlock
    396  */
    397 static int
    398 pnwDRMCmdBuf(int fd, int ioctl_offset, psb_buffer_p *buffer_list, int buffer_count, unsigned cmdBufHandle,
    399              unsigned cmdBufOffset, unsigned cmdBufSize,
    400              unsigned relocBufHandle, unsigned relocBufOffset,
    401              unsigned numRelocs, int __maybe_unused damage,
    402              unsigned engine, unsigned fence_flags, struct psb_ttm_fence_rep *fence_rep)
    403 {
    404     drm_psb_cmdbuf_arg_t ca;
    405     struct psb_validate_arg *arg_list;
    406     int i;
    407     int ret;
    408     uint64_t mask = PSB_GPU_ACCESS_MASK;
    409 
    410     arg_list = (struct psb_validate_arg *) calloc(1, sizeof(struct psb_validate_arg) * buffer_count);
    411     if (arg_list == NULL) {
    412         drv_debug_msg(VIDEO_DEBUG_ERROR, "Allocate memory failed\n");
    413         return -ENOMEM;
    414     }
    415 
    416     for (i = 0; i < buffer_count; i++) {
    417         struct psb_validate_arg *arg = &(arg_list[i]);
    418         struct psb_validate_req *req = &arg->d.req;
    419 
    420         req->next = (unsigned long) & (arg_list[i+1]);
    421 
    422         req->buffer_handle = wsbmKBufHandle(wsbmKBuf(buffer_list[i]->drm_buf));
    423         //req->group = 0;
    424         req->set_flags = (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE) & mask;
    425         req->clear_flags = (~(PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)) & mask;
    426 #if 1
    427         req->presumed_gpu_offset = (uint64_t)wsbmBOOffsetHint(buffer_list[i]->drm_buf);
    428         req->presumed_flags = PSB_USE_PRESUMED;
    429 #else
    430         req->presumed_flags = 0;
    431 #endif
    432         req->pad64 = (uint32_t)buffer_list[i]->pl_flags;
    433     }
    434     arg_list[buffer_count-1].d.req.next = 0;
    435 
    436     ca.buffer_list = (uint64_t)((unsigned long)arg_list);
    437     ca.cmdbuf_handle = cmdBufHandle;
    438     ca.cmdbuf_offset = cmdBufOffset;
    439     ca.cmdbuf_size = cmdBufSize;
    440     ca.reloc_handle = relocBufHandle;
    441     ca.reloc_offset = relocBufOffset;
    442     ca.num_relocs = numRelocs;
    443     ca.engine = engine;
    444     ca.fence_flags = fence_flags;
    445     ca.fence_arg = (uint64_t)((unsigned long)fence_rep);
    446 
    447     do {
    448         ret = drmCommandWrite(fd, ioctl_offset, &ca, sizeof(ca));
    449     } while (ret == EAGAIN);
    450 
    451     if (ret)
    452         goto out;
    453 
    454     for (i = 0; i < buffer_count; i++) {
    455         struct psb_validate_arg *arg = &(arg_list[i]);
    456         struct psb_validate_rep *rep = &arg->d.rep;
    457 
    458         if (!arg->handled) {
    459             ret = -EFAULT;
    460             goto out;
    461         }
    462         if (arg->ret != 0) {
    463             ret = arg->ret;
    464             goto out;
    465         }
    466         wsbmUpdateKBuf(wsbmKBuf(buffer_list[i]->drm_buf),
    467                        rep->gpu_offset, rep->placement, rep->fence_type_mask);
    468     }
    469 out:
    470     free(arg_list);
    471     for (i = 0; i < buffer_count; i++) {
    472         /*
    473          * Buffer no longer queued in userspace
    474          */
    475         switch (buffer_list[i]->status) {
    476         case psb_bs_queued:
    477             buffer_list[i]->status = psb_bs_ready;
    478             break;
    479 
    480         case psb_bs_abandoned:
    481             psb_buffer_destroy(buffer_list[i]);
    482             free(buffer_list[i]);
    483             break;
    484 
    485         default:
    486             /* Not supposed to happen */
    487             ASSERT(0);
    488         }
    489     }
    490 
    491     return ret;
    492 }
    493 
    494 #if 0
    495 static struct _WsbmFenceObject *
    496 lnc_fence_wait(psb_driver_data_p driver_data,
    497                struct psb_ttm_fence_rep *fence_rep, int *status)
    498 
    499 {
    500     struct _WsbmFenceObject *fence = NULL;
    501     int ret = -1;
    502 
    503     /* copy fence information */
    504     if (fence_rep->error != 0) {
    505         drv_debug_msg(VIDEO_DEBUG_ERROR, "drm failed to create a fence"
    506                            " and has idled the HW\n");
    507         DEBUG_FAILURE_RET;
    508         return NULL;
    509     }
    510 
    511     fence = wsbmFenceCreate(driver_data->fence_mgr, fence_rep->fence_class,
    512                             fence_rep->fence_type,
    513                             (unsigned char *)fence_rep->handle,
    514                             0);
    515     if (fence)
    516         *status = wsbmFenceFinish(fence, fence_rep->fence_type, 0);
    517 
    518     return fence;
    519 }
    520 #endif
    521 
    522 /*
    523  * Submits the current cmdbuf
    524  *
    525  * Returns 0 on success
    526  */
    527 int pnw_context_submit_cmdbuf(object_context_p __maybe_unused obj_context)
    528 {
    529     return 0;
    530 }
    531 
    532 
    533 
    534 /*
    535  * FrameSkip is only meaningful for RC enabled mode
    536  * Topaz raises this flag after surface N encoding is finished (vaSyncSurface gets back)
    537  * then for the next encode surface N+1 (ctx->src_surface) frameskip flag is cleared in vaBeginPicuture
    538  * and is always set in vaEndPicture:lnc_PatchRCMode
    539  * vaQuerySurfaceStatus is supposed only to be called after vaEndPicture/vaSyncSurface,
    540  * The caller should ensure the surface pertains to an encode context
    541  */
    542 int pnw_surface_get_frameskip(psb_driver_data_p __maybe_unused driver_data,
    543                               psb_surface_p surface,
    544                               int *frame_skip)
    545 {
    546     /* bit31 indicate if frameskip is already settled, it is used to record the frame skip flag for old surfaces
    547      * bit31 is cleared when the surface is used as encode render target or reference/reconstrucure target
    548      */
    549     if (GET_SURFACE_INFO_skipped_flag(surface) & SURFACE_INFO_SKIP_FLAG_SETTLED) {
    550         *frame_skip = GET_SURFACE_INFO_skipped_flag(surface) & 1;
    551     } else
    552         *frame_skip = 0;
    553 
    554     return 0;
    555 }
    556 
    557 
    558 /*
    559  * Flushes all cmdbufs
    560  */
    561 int pnw_context_flush_cmdbuf(object_context_p obj_context)
    562 {
    563     pnw_cmdbuf_p cmdbuf = obj_context->pnw_cmdbuf;
    564     psb_driver_data_p driver_data = obj_context->driver_data;
    565     unsigned int fence_flags;
    566     struct psb_ttm_fence_rep fence_rep;
    567     unsigned int reloc_offset;
    568     unsigned int num_relocs;
    569     int ret;
    570     unsigned int cmdbuffer_size = (unsigned char *) cmdbuf->cmd_idx - cmdbuf->cmd_start; /* In bytes */
    571 
    572     ASSERT(cmdbuffer_size < CMD_SIZE);
    573     ASSERT((unsigned char *) cmdbuf->cmd_idx < CMD_END(cmdbuf));
    574     /* LOCK */
    575     ret = LOCK_HARDWARE(driver_data);
    576     if (ret) {
    577         UNLOCK_HARDWARE(driver_data);
    578         DEBUG_FAILURE_RET;
    579         return ret;
    580     }
    581 
    582     /* Now calculate the total number of relocations */
    583     reloc_offset = cmdbuf->reloc_base - cmdbuf->cmd_base;
    584     num_relocs = (((unsigned char *) cmdbuf->reloc_idx) - cmdbuf->reloc_base) / sizeof(struct drm_psb_reloc);
    585 
    586     pnw_cmdbuf_unmap(cmdbuf);
    587 
    588     ASSERT(NULL == cmdbuf->reloc_base);
    589 
    590     if (psb_video_trace_fp)
    591         fence_flags = 0;
    592     else
    593         fence_flags = DRM_PSB_FENCE_NO_USER;
    594 
    595 #ifndef LNC_ENGINE_ENCODE
    596 #define LNC_ENGINE_ENCODE  5
    597 #endif
    598 
    599     wsbmWriteLockKernelBO();
    600     ret = pnwDRMCmdBuf(driver_data->drm_fd, driver_data->execIoctlOffset, /* FIXME Still use ioctl cmd? */
    601                        cmdbuf->buffer_refs, cmdbuf->buffer_refs_count, wsbmKBufHandle(wsbmKBuf(cmdbuf->buf.drm_buf)),
    602                        0, cmdbuffer_size,/*unsigned cmdBufSize*/
    603                        wsbmKBufHandle(wsbmKBuf(cmdbuf->buf.drm_buf)), reloc_offset, num_relocs,
    604                        0, LNC_ENGINE_ENCODE, fence_flags, &fence_rep); /* FIXME use LNC_ENGINE_ENCODE */
    605 
    606     wsbmWriteUnlockKernelBO();
    607     UNLOCK_HARDWARE(driver_data);
    608 
    609     if (ret) {
    610         obj_context->pnw_cmdbuf = NULL;
    611 
    612         DEBUG_FAILURE_RET;
    613         return ret;
    614     }
    615 
    616 #if 0
    617     int status = -1;
    618     struct _WsbmFenceObject *fence = NULL;
    619 
    620     fence = lnc_fence_wait(driver_data, &fence_rep, &status);
    621     drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_fence_wait returns: %d (fence=0x%08x)\n", status, fence);
    622 
    623     if (fence)
    624         wsbmFenceUnreference(fence);
    625 #endif
    626 
    627     obj_context->pnw_cmdbuf = NULL;
    628 
    629     return 0;
    630 }
    631 
    632 
    633 int pnw_get_parallel_core_number(object_context_p obj_context)
    634 {
    635 
    636     context_ENC_p ctx = (context_ENC_p)(obj_context->format_data);
    637     return ctx->ParallelCores;
    638 
    639 }
    640