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  *
     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