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 #include <sys/types.h>
     31 #include "psb_buffer.h"
     32 
     33 #include <errno.h>
     34 #include <stdlib.h>
     35 #include <unistd.h>
     36 #include <wsbm/wsbm_manager.h>
     37 
     38 #ifdef ANDROID
     39 #ifdef BAYTRAIL
     40 #include <linux/vxd_drm.h>
     41 #else
     42 #include <drm/ttm/ttm_placement.h>
     43 #include <linux/psb_drm.h>
     44 #endif
     45 #else
     46 #include <psb_drm.h>
     47 #endif
     48 
     49 #include "psb_def.h"
     50 #include "psb_drv_debug.h"
     51 #include "tng_cmdbuf.h"
     52 
     53 #ifndef BAYTRAIL
     54 #include <pnw_cmdbuf.h>
     55 #include "pnw_jpeg.h"
     56 #include "pnw_H264ES.h"
     57 #include "tng_jpegES.h"
     58 #endif
     59 
     60 #include "vsp_fw.h"
     61 /*
     62  * Create buffer
     63  */
     64 VAStatus psb_buffer_create(psb_driver_data_p driver_data,
     65                            unsigned int size,
     66                            psb_buffer_type_t type,
     67                            psb_buffer_p buf
     68                           )
     69 {
     70     VAStatus vaStatus = VA_STATUS_SUCCESS;
     71     int allignment;
     72     uint32_t placement;
     73     int ret;
     74 
     75     /* reset rar_handle to NULL */
     76     buf->rar_handle = 0;
     77     buf->buffer_ofs = 0;
     78 
     79     buf->type = type;
     80     buf->driver_data = driver_data; /* only for RAR buffers */
     81     buf->size = size;
     82     /* TODO: Mask values are a guess */
     83     switch (type) {
     84     case psb_bt_cpu_vpu:
     85         allignment = 1;
     86         placement = DRM_PSB_FLAG_MEM_MMU;
     87         break;
     88     case psb_bt_cpu_vpu_shared:
     89         allignment = 1;
     90         placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_SHARED;
     91         break;
     92     case psb_bt_surface:
     93         allignment = 0;
     94         placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_SHARED;
     95         if (IS_CTP(driver_data))  /* CTP support cache snoop */
     96             placement |= WSBM_PL_FLAG_CACHED;
     97         break;
     98     case psb_bt_surface_tt:
     99         allignment = 0;
    100         placement = WSBM_PL_FLAG_TT | WSBM_PL_FLAG_NO_EVICT | WSBM_PL_FLAG_SHARED;
    101         break;
    102 #ifdef PSBVIDEO_MSVDX_DEC_TILING
    103     case psb_bt_surface_tiling:
    104             drv_debug_msg(VIDEO_DEBUG_GENERAL, "Allocate tiled surface from TT heap\n");
    105             placement =  WSBM_PL_FLAG_TT | WSBM_PL_FLAG_SHARED;
    106             allignment = 2048 * 16; /* Tiled row aligned */
    107         break;
    108     case psb_bt_mmu_tiling:
    109             placement =  DRM_PSB_FLAG_MEM_MMU_TILING | WSBM_PL_FLAG_SHARED;
    110             allignment = 2048 * 16; /* Tiled row aligned */
    111         break;
    112 #endif
    113     case psb_bt_cpu_vpu_cached:
    114         allignment = 1;
    115         placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_CACHED;
    116         break;
    117     case psb_bt_vpu_only:
    118         allignment = 1;
    119         placement = DRM_PSB_FLAG_MEM_MMU;
    120         break;
    121     case psb_bt_cpu_only:
    122         allignment = 1;
    123         placement = WSBM_PL_FLAG_SYSTEM | WSBM_PL_FLAG_CACHED;
    124         break;
    125 #if PSB_MFLD_DUMMY_CODE
    126     case psb_bt_camera:
    127         allignment = 1;
    128         placement = WSBM_PL_FLAG_SHARED;
    129         break;
    130 #endif
    131 #ifdef ANDROID
    132 #ifndef BAYTRAIL
    133     case psb_bt_imr:
    134         allignment = 1;
    135         placement = TTM_PL_FLAG_IMR | WSBM_PL_FLAG_SHARED;
    136         break;
    137 #endif
    138 #endif
    139     default:
    140         vaStatus = VA_STATUS_ERROR_UNKNOWN;
    141         DEBUG_FAILURE;
    142         return vaStatus;
    143     }
    144     ret = LOCK_HARDWARE(driver_data);
    145     if (ret) {
    146         UNLOCK_HARDWARE(driver_data);
    147         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    148         DEBUG_FAILURE_RET;
    149         return vaStatus;
    150     }
    151 
    152 #ifdef VA_EMULATOR
    153     placement |= WSBM_PL_FLAG_SHARED;
    154 #endif
    155 
    156 #ifndef ANDROID
    157     if(!(placement & WSBM_PL_FLAG_SYSTEM)) {
    158         //drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: buffer->pl_flags 0x%08x\n", __func__, placement);
    159         placement &= ~WSBM_PL_MASK_MEM;
    160         placement &= ~WSBM_PL_FLAG_NO_EVICT;
    161         placement |= TTM_PL_FLAG_VRAM;
    162         //drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: repleace buffer->pl_flags 0x%08x\n", __func__, placement);
    163     }
    164 #endif
    165 
    166 #ifdef MSVDX_VA_EMULATOR
    167     placement |= WSBM_PL_FLAG_SHARED;
    168 #endif
    169 
    170     if(allignment < 4096)
    171         allignment = 4096; /* temporily more safe */
    172 
    173     //drv_debug_msg(VIDEO_DEBUG_ERROR, "FIXME: should use geetpagesize() ?\n");
    174     ret = wsbmGenBuffers(driver_data->main_pool, 1, &buf->drm_buf,
    175                          allignment, placement);
    176     if (!buf->drm_buf) {
    177         drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n");
    178         UNLOCK_HARDWARE(driver_data);
    179         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    180     }
    181 
    182     /* here use the placement when gen buffer setted */
    183     ret = wsbmBOData(buf->drm_buf, size, NULL, NULL, 0);
    184     UNLOCK_HARDWARE(driver_data);
    185     if (ret) {
    186         drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc wsbm buffers\n");
    187         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    188     }
    189 
    190     if (placement & WSBM_PL_FLAG_TT)
    191         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create BO with TT placement (%d byte),BO GPU offset hint=0x%08x\n",
    192                                  size, wsbmBOOffsetHint(buf->drm_buf));
    193 
    194     buf->pl_flags = placement;
    195     buf->status = psb_bs_ready;
    196     buf->wsbm_synccpu_flag = 0;
    197 
    198     return VA_STATUS_SUCCESS;
    199 }
    200 
    201 /*
    202  * Create buffer
    203  */
    204 VAStatus psb_buffer_create_from_ub(psb_driver_data_p driver_data,
    205                            unsigned int size,
    206                            psb_buffer_type_t type,
    207                            psb_buffer_p buf,
    208                            void * vaddr,
    209                            int fd,
    210                            unsigned int flags
    211                           )
    212 {
    213     VAStatus vaStatus = VA_STATUS_SUCCESS;
    214     int allignment;
    215     uint32_t placement;
    216     int ret;
    217 
    218     /* reset rar_handle to NULL */
    219     buf->rar_handle = 0;
    220     buf->buffer_ofs = 0;
    221 
    222     buf->type = type;
    223     buf->driver_data = driver_data; /* only for RAR buffers */
    224     buf->user_ptr = vaddr;
    225     buf->fd = fd;
    226 
    227     /* Xvideo will share surface buffer, set SHARED flag
    228     */
    229     placement =  DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_SHARED ;
    230 
    231     ret = LOCK_HARDWARE(driver_data);
    232     if (ret) {
    233         UNLOCK_HARDWARE(driver_data);
    234         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    235         DEBUG_FAILURE_RET;
    236         return vaStatus;
    237     }
    238 
    239     allignment = 4096; /* temporily more safe */
    240 #ifdef PSBVIDEO_MSVDX_DEC_TILING
    241     if (type == psb_bt_mmu_tiling) {
    242         placement =  DRM_PSB_FLAG_MEM_MMU_TILING | WSBM_PL_FLAG_SHARED ;
    243         allignment = 2048 * 16; /* Tiled row aligned */
    244     }
    245 #endif
    246 
    247     if (flags & PSB_USER_BUFFER_WC)
    248 	placement |= WSBM_PL_FLAG_WC;
    249     else if (flags & PSB_USER_BUFFER_UNCACHED)
    250 	placement |= WSBM_PL_FLAG_UNCACHED;
    251     else
    252 	placement |= WSBM_PL_FLAG_CACHED;
    253 
    254     //drv_debug_msg(VIDEO_DEBUG_ERROR, "FIXME: should use geetpagesize() ?\n");
    255     ret = wsbmGenBuffers(driver_data->main_pool, 1, &buf->drm_buf,
    256     allignment, placement);
    257     if (!buf->drm_buf) {
    258         drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n");
    259         UNLOCK_HARDWARE(driver_data);
    260         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    261     }
    262 
    263     /* here use the placement when gen buffer setted */
    264     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create BO from user buffer %p, size=%d, fd = %d\n", vaddr, size, fd);
    265 
    266     ret = wsbmBODataUB(buf->drm_buf, size, NULL, NULL, 0, vaddr, fd);
    267     if (ret) {
    268         drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to alloc wsbm buffers, buf->drm_buf is 0x%x, size is %d, vaddr is 0x%x, fd=%d\n", buf->drm_buf, size, vaddr, fd);
    269         UNLOCK_HARDWARE(driver_data);
    270         return 1;
    271     }
    272 
    273     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create BO from user buffer 0x%08x (%d byte), fd=%d, BO GPU offset hint=0x%08x\n",
    274     vaddr, size, fd, wsbmBOOffsetHint(buf->drm_buf));
    275 
    276     buf->pl_flags = placement;
    277     buf->status = psb_bs_ready;
    278     buf->wsbm_synccpu_flag = 0;
    279 
    280     UNLOCK_HARDWARE(driver_data);
    281     return VA_STATUS_SUCCESS;
    282 }
    283 
    284 #if 0
    285 /*
    286  * buffer setstatus
    287  *
    288  * Returns 0 on success
    289  */
    290 int psb_buffer_setstatus(psb_buffer_p buf, uint32_t set_placement, uint32_t clr_placement)
    291 {
    292     int ret = 0;
    293 
    294     ASSERT(buf);
    295     ASSERT(buf->driver_data);
    296 
    297     ret = wsbmBOSetStatus(buf->drm_buf, set_placement, clr_placement);
    298     if (ret == 0)
    299         buf->pl_flags = set_placement;
    300 
    301     return ret;
    302 }
    303 #endif
    304 
    305 VAStatus psb_buffer_reference(psb_driver_data_p driver_data,
    306                               psb_buffer_p buf,
    307                               psb_buffer_p reference_buf
    308                              )
    309 {
    310     int ret = 0;
    311     VAStatus vaStatus = VA_STATUS_SUCCESS;
    312 
    313     memcpy(buf, reference_buf, sizeof(*buf));
    314     buf->drm_buf = NULL;
    315 
    316     ret = LOCK_HARDWARE(driver_data);
    317     if (ret) {
    318         UNLOCK_HARDWARE(driver_data);
    319         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    320         DEBUG_FAILURE_RET;
    321         return vaStatus;
    322     }
    323 
    324     ret = wsbmGenBuffers(driver_data->main_pool,
    325                          1,
    326                          &buf->drm_buf,
    327                          4096,  /* page alignment */
    328                          0);
    329     if (!buf->drm_buf) {
    330         drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n");
    331         UNLOCK_HARDWARE(driver_data);
    332         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    333     }
    334 
    335     ret = wsbmBOSetReferenced(buf->drm_buf, wsbmKBufHandle(wsbmKBuf(reference_buf->drm_buf)));
    336     UNLOCK_HARDWARE(driver_data);
    337     if (ret) {
    338         drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc wsbm buffers\n");
    339         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    340     }
    341 
    342     return VA_STATUS_SUCCESS;
    343 }
    344 
    345 VAStatus psb_kbuffer_reference(psb_driver_data_p driver_data,
    346                                psb_buffer_p buf,
    347                                int kbuf_handle
    348                               )
    349 {
    350     int ret = 0;
    351     VAStatus vaStatus = VA_STATUS_SUCCESS;
    352 
    353     buf->drm_buf = NULL;
    354 
    355     ret = LOCK_HARDWARE(driver_data);
    356     if (ret) {
    357         UNLOCK_HARDWARE(driver_data);
    358         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    359         DEBUG_FAILURE_RET;
    360         return vaStatus;
    361     }
    362 
    363     ret = wsbmGenBuffers(driver_data->main_pool,
    364                          1,
    365                          &buf->drm_buf,
    366                          4096,  /* page alignment */
    367                          0);
    368     if (!buf->drm_buf) {
    369         drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n");
    370         UNLOCK_HARDWARE(driver_data);
    371         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    372     }
    373 
    374     ret = wsbmBOSetReferenced(buf->drm_buf, kbuf_handle);
    375     UNLOCK_HARDWARE(driver_data);
    376     if (ret) {
    377         drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc wsbm buffers\n");
    378         return VA_STATUS_ERROR_ALLOCATION_FAILED;
    379     }
    380     buf->pl_flags = wsbmBOPlacementHint(buf->drm_buf);
    381     buf->type = psb_bt_surface;
    382     buf->status = psb_bs_ready;
    383 
    384     return VA_STATUS_SUCCESS;
    385 }
    386 /*
    387  * Destroy buffer
    388  */
    389 void psb_buffer_destroy(psb_buffer_p buf)
    390 {
    391     ASSERT(buf);
    392     if (buf->drm_buf == NULL)
    393         return;
    394     if (psb_bs_unfinished != buf->status) {
    395         ASSERT(buf->driver_data);
    396         wsbmBOUnreference(&buf->drm_buf);
    397         if (buf->rar_handle)
    398             buf->rar_handle = 0;
    399         buf->driver_data = NULL;
    400         buf->status = psb_bs_unfinished;
    401     }
    402 }
    403 
    404 /*
    405  * Map buffer
    406  *
    407  * Returns 0 on success
    408  */
    409 int psb_buffer_map(psb_buffer_p buf, unsigned char **address /* out */)
    410 {
    411     int ret;
    412 
    413     ASSERT(buf);
    414     ASSERT(buf->driver_data);
    415 
    416     /* multiple mapping not allowed */
    417     if (buf->wsbm_synccpu_flag) {
    418         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Multiple mapping request detected, unmap previous mapping\n");
    419         drv_debug_msg(VIDEO_DEBUG_GENERAL, "Need to fix application to unmap at first, then request second mapping request\n");
    420 
    421         psb_buffer_unmap(buf);
    422     }
    423 
    424     /* don't think TG deal with READ/WRITE differently */
    425     buf->wsbm_synccpu_flag = WSBM_SYNCCPU_READ | WSBM_SYNCCPU_WRITE;
    426     if (psb_video_trace_fp) {
    427         wsbmBOWaitIdle(buf->drm_buf, 0);
    428     } else {
    429         ret = wsbmBOSyncForCpu(buf->drm_buf, buf->wsbm_synccpu_flag);
    430         if (ret) {
    431             drv_debug_msg(VIDEO_DEBUG_ERROR, "faild to sync bo for cpu\n");
    432             return ret;
    433         }
    434     }
    435 
    436     if (buf->user_ptr) /* user mode buffer */
    437         *address = buf->user_ptr;
    438     else
    439         *address = wsbmBOMap(buf->drm_buf, buf->wsbm_synccpu_flag);
    440 
    441     if (*address == NULL) {
    442         drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to map buffer\n");
    443         return -1;
    444     }
    445 
    446     return 0;
    447 }
    448 
    449 /*
    450  * Unmap buffer
    451  *
    452  * Returns 0 on success
    453  */
    454 int psb_buffer_unmap(psb_buffer_p buf)
    455 {
    456     ASSERT(buf);
    457     ASSERT(buf->driver_data);
    458 
    459     if (buf->wsbm_synccpu_flag)
    460         (void) wsbmBOReleaseFromCpu(buf->drm_buf, buf->wsbm_synccpu_flag);
    461 
    462     buf->wsbm_synccpu_flag = 0;
    463 
    464     if ((buf->type != psb_bt_user_buffer) && !buf->handle)
    465         wsbmBOUnmap(buf->drm_buf);
    466 
    467     return 0;
    468 }
    469 
    470 #define _MRFL_DEBUG_CODED_
    471 
    472 #ifdef _MRFL_DEBUG_CODED_
    473 static void psb__trace_coded(VACodedBufferSegment *vaCodedBufSeg)
    474 {
    475     int i, j;
    476     int uiPipeIndex = -1;
    477     unsigned int *pBuf = NULL;
    478     do {
    479         ++uiPipeIndex;
    480         drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: pipe num %d, size = %d\n", __FUNCTION__, uiPipeIndex, vaCodedBufSeg[uiPipeIndex].size);
    481         pBuf = (unsigned int *)(vaCodedBufSeg[uiPipeIndex].buf);
    482         pBuf -= 16;
    483         for (i = 0; i < 6; i++) {
    484             for (j = 0; j < 4; j++) {
    485                 drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: 0x%08x\n", __FUNCTION__, pBuf[(i*4) + j]);
    486             }
    487          }
    488         drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: \n", __FUNCTION__);
    489     } while (vaCodedBufSeg[uiPipeIndex].next);
    490 
    491 	return ;
    492 }
    493 #endif
    494 
    495 #define PROFILE_H264(profile) ((profile>=VAProfileH264Baseline && profile <=VAProfileH264High) || \
    496                                (profile == VAProfileH264ConstrainedBaseline))
    497 static void tng_get_coded_data(
    498     object_buffer_p obj_buffer,
    499     unsigned char *raw_codedbuf
    500 )
    501 {
    502     object_context_p obj_context = obj_buffer->context;
    503     VACodedBufferSegment *vaCodedBufSeg = &obj_buffer->codedbuf_mapinfo[0];
    504     int iPipeIndex = 0;
    505     unsigned int uiPipeNum = tng_get_pipe_number(obj_context);
    506     unsigned int uiBufOffset = tng_align_KB(obj_buffer->size >> 1);
    507     unsigned long *ptmp = NULL;
    508     int tmp;
    509 
    510     drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s pipenum = 0x%x\n", __FUNCTION__, uiPipeNum);
    511     drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s offset  = 0x%x\n", __FUNCTION__, uiBufOffset);
    512 
    513     tmp = vaCodedBufSeg[iPipeIndex].size = *(unsigned int *)((unsigned long)raw_codedbuf);
    514 
    515     /*
    516      * This is used for DRM over WiDi which only uses H264 BP
    517      * Tangier IED encryption operates on the chunks with 16bytes, and we must include
    518      * the extra bytes beyond slice data as a whole chunk for decrption
    519      * We simply include the padding bytes regardless of IED enable or disable
    520      */
    521     if (PROFILE_H264(obj_context->profile) && (tmp % 16 != 0)) {
    522 	tmp = (tmp + 15) & (~15);
    523 	drv_debug_msg(VIDEO_DEBUG_GENERAL, "Force slice size from %d to %d\n",
    524                       vaCodedBufSeg[iPipeIndex].size, tmp);
    525 	vaCodedBufSeg[iPipeIndex].size  = tmp;
    526     }
    527 
    528     vaCodedBufSeg[iPipeIndex].buf = (unsigned char *)(((unsigned int *)((unsigned long)raw_codedbuf)) + 16); /* skip 4DWs */
    529 
    530     ptmp = (unsigned long *)((unsigned long)raw_codedbuf);
    531     vaCodedBufSeg[iPipeIndex].reserved = (ptmp[1] >> 6) & 0xf;
    532     vaCodedBufSeg[iPipeIndex].next = NULL;
    533 
    534 
    535     if (uiPipeNum == 2) {
    536         /*The second part of coded buffer which generated by core 2 is the
    537          * first part of encoded clip, while the first part of coded buffer
    538          * is the second part of encoded clip.*/
    539         ++iPipeIndex;
    540         vaCodedBufSeg[iPipeIndex - 1].next = &vaCodedBufSeg[iPipeIndex];
    541         tmp = vaCodedBufSeg[iPipeIndex].size = *(unsigned int *)((unsigned long)raw_codedbuf + uiBufOffset);
    542 
    543         /*
    544          * This is used for DRM over WiDi which only uses H264 BP
    545          * Tangier IED encryption operates on the chunks with 16bytes, and we must include
    546          * the extra bytes beyond slice data as a whole chunk for decryption
    547          * We simply include the padding bytes regardless of IED enable or disable
    548          */
    549         if (PROFILE_H264(obj_context->profile) && (tmp % 16 != 0)) {
    550             tmp = (tmp + 15) & (~15);
    551             drv_debug_msg(VIDEO_DEBUG_GENERAL,"Force slice size from %d to %d\n",
    552                           vaCodedBufSeg[iPipeIndex].size, tmp);
    553 
    554             vaCodedBufSeg[iPipeIndex].size  = tmp;
    555         }
    556 
    557         vaCodedBufSeg[iPipeIndex].buf = (unsigned char *)(((unsigned int *)((unsigned long)raw_codedbuf + uiBufOffset)) + 16); /* skip 4DWs */
    558         vaCodedBufSeg[iPipeIndex].reserved = vaCodedBufSeg[iPipeIndex - 1].reserved;
    559         vaCodedBufSeg[iPipeIndex].next = NULL;
    560     }
    561 
    562 #ifdef _MRFL_DEBUG_CODED_
    563     psb__trace_coded(vaCodedBufSeg);
    564 #endif
    565 
    566     return ;
    567 }
    568 
    569 /*
    570  * Return special data structure for codedbuffer
    571  *
    572  * Returns 0 on success
    573  */
    574 #define CONFIG(id)  ((object_config_p) object_heap_lookup( &driver_data->config_heap, id ))
    575 #define INIT_DRIVER_DATA    psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
    576 int psb_codedbuf_map_mangle(
    577     VADriverContextP ctx,
    578     object_buffer_p obj_buffer,
    579     void **pbuf /* out */
    580 )
    581 {
    582     object_context_p obj_context = obj_buffer->context;
    583     INIT_DRIVER_DATA;
    584     VACodedBufferSegment *p = &obj_buffer->codedbuf_mapinfo[0];
    585     unsigned char *raw_codedbuf;
    586     VAStatus vaStatus = VA_STATUS_SUCCESS;
    587     unsigned int next_buf_off;
    588     uint32_t i;
    589 
    590     CHECK_INVALID_PARAM(pbuf == NULL);
    591 
    592     if (NULL == obj_context) {
    593         vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    594         DEBUG_FAILURE;
    595 
    596         psb_buffer_unmap(obj_buffer->psb_buffer);
    597         obj_buffer->buffer_data = NULL;
    598 
    599         return vaStatus;
    600     }
    601 
    602     raw_codedbuf = *pbuf;
    603     /* reset the mapinfo */
    604     memset(obj_buffer->codedbuf_mapinfo, 0, sizeof(obj_buffer->codedbuf_mapinfo));
    605 
    606     *pbuf = p = &obj_buffer->codedbuf_mapinfo[0];
    607 #ifdef PSBVIDEO_MRFL
    608     if (IS_MRFL(driver_data)) {
    609         object_config_p obj_config = CONFIG(obj_context->config_id);
    610         if (NULL == obj_config) {
    611             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    612             DEBUG_FAILURE;
    613 
    614             psb_buffer_unmap(obj_buffer->psb_buffer);
    615             obj_buffer->buffer_data = NULL;
    616 
    617             return vaStatus;
    618         }
    619 
    620         if (VAProfileJPEGBaseline != obj_config->profile
    621             && (*((unsigned long *) raw_codedbuf + 1) & SKIP_NEXT_FRAME) != 0) {
    622             /*Set frame skip flag*/
    623             tng_set_frame_skip_flag(obj_context);
    624         }
    625         switch (obj_config->profile) {
    626             case VAProfileMPEG4Simple:
    627             case VAProfileMPEG4AdvancedSimple:
    628             case VAProfileMPEG4Main:
    629 
    630             case VAProfileH264Baseline:
    631             case VAProfileH264Main:
    632             case VAProfileH264High:
    633             case VAProfileH264StereoHigh:
    634             case VAProfileH264ConstrainedBaseline:
    635             case VAProfileH263Baseline:
    636                 /* 1st segment */
    637                 tng_get_coded_data(obj_buffer, raw_codedbuf);
    638 #if 0
    639                 p->size = *((unsigned long *) raw_codedbuf);
    640                 p->buf = (unsigned char *)((unsigned long *) raw_codedbuf + 16); /* skip 16DWs */
    641                 p->next = NULL;
    642 #ifdef _MRFL_DEBUG_CODED_
    643                 psb__trace_coded((unsigned int*)raw_codedbuf);
    644                 psb__trace_coded(p);
    645 #endif
    646 #endif
    647                 break;
    648             case VAProfileVP8Version0_3:
    649             {
    650                 /* multi segments*/
    651 		struct VssVp8encEncodedFrame *t = (struct VssVp8encEncodedFrame *) (raw_codedbuf);
    652 		int concatenate = 1;
    653 #if 0
    654 		for (i = 0; i < t->partitions - 1; i++) {
    655                     if (t->partition_start[i+1] != t->partition_start[i] + t->partition_size[i])
    656                         concatenate = 0;
    657 		}
    658 #endif
    659 		/* reference frame surface_id */
    660                 /* default is recon_buffer_mode ==0 */
    661                 p->reserved = t->surfaceId_of_ref_frame[3];
    662 
    663 		if (concatenate) {
    664                     /* partitions are concatenate */
    665                     p->buf = t->coded_data;
    666                     p->size = t->frame_size;
    667                     if(t->frame_size == 0){
    668                         drv_debug_msg(VIDEO_DEBUG_ERROR,"Frame size is zero, Force it to 3, encoder status is 0x%x\n", t->status);
    669                         p->size = 3;
    670                         t->coded_data[0]=0;
    671                     }
    672                     p->next = NULL;
    673 		} else {
    674                     for (i = 0; i < t->partitions; i++) {
    675                         /* partition not consecutive */
    676                         p->buf = t->coded_data + t->partition_start[i] - t->partition_start[0];
    677                         p->size += t->partition_size[i];
    678                         p->next = &p[1];
    679                         p++;
    680 		    }
    681 		    p--;
    682 		    p->next = NULL;
    683 		}
    684 
    685 		break;
    686             }
    687             case VAProfileJPEGBaseline:
    688                 /* 3~6 segment */
    689                 tng_jpeg_AppendMarkers(obj_context, raw_codedbuf);
    690                 next_buf_off = 0;
    691                 /*Max resolution 4096x4096 use 6 segments*/
    692                 for (i = 0; i < PTG_JPEG_MAX_SCAN_NUM + 1; i++) {
    693                     p->size = *(unsigned long *)((unsigned long)raw_codedbuf + next_buf_off);  /* ui32BytesUsed in HEADER_BUFFER*/
    694                     p->buf = (unsigned char *)((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 4);  /* skip 4DWs (HEADER_BUFFER) */
    695                     next_buf_off = *((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 3);  /* ui32Reserved3 in HEADER_BUFFER*/
    696 
    697                     drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG coded buffer segment %d size: %d\n", i, p->size);
    698                     drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG coded buffer next segment %d offset: %d\n", i + 1, next_buf_off);
    699 
    700                     if (next_buf_off == 0) {
    701                         p->next = NULL;
    702                         break;
    703                     } else
    704                         p->next = &p[1];
    705                     p++;
    706                 }
    707                 break;
    708 
    709             default:
    710                 drv_debug_msg(VIDEO_DEBUG_ERROR, "unexpected case\n");
    711 
    712                 psb_buffer_unmap(obj_buffer->psb_buffer);
    713                 obj_buffer->buffer_data = NULL;
    714                 break;
    715         }
    716     }
    717 #endif
    718 #ifdef PSBVIDEO_MFLD
    719     if (IS_MFLD(driver_data)){ /* MFLD */
    720         object_config_p obj_config = CONFIG(obj_context->config_id);
    721 
    722         if (NULL == obj_config) {
    723             vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
    724             DEBUG_FAILURE;
    725 
    726             psb_buffer_unmap(obj_buffer->psb_buffer);
    727             obj_buffer->buffer_data = NULL;
    728 
    729             return vaStatus;
    730         }
    731 
    732         if (VAProfileJPEGBaseline != obj_config->profile
    733             && (*((unsigned long *) raw_codedbuf + 1) & SKIP_NEXT_FRAME) != 0) {
    734             /*Set frame skip flag*/
    735             pnw_set_frame_skip_flag(obj_context);
    736         }
    737         switch (obj_config->profile) {
    738         case VAProfileMPEG4Simple:
    739         case VAProfileMPEG4AdvancedSimple:
    740         case VAProfileMPEG4Main:
    741             /* one segment */
    742             p->size = *((unsigned long *) raw_codedbuf);
    743             p->buf = (unsigned char *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */
    744             drv_debug_msg(VIDEO_DEBUG_GENERAL, "coded buffer size %d\n", p->size);
    745             break;
    746 
    747         case VAProfileH264Baseline:
    748         case VAProfileH264Main:
    749         case VAProfileH264High:
    750         case VAProfileH264ConstrainedBaseline:
    751             i = 0;
    752             next_buf_off = ~0xf & (obj_buffer->size / pnw_get_parallel_core_number(obj_context));
    753             if (pnw_get_parallel_core_number(obj_context) == 2) {
    754                 /*The second part of coded buffer which generated by core 2 is the
    755                  * first part of encoded clip, while the first part of coded buffer
    756                  * is the second part of encoded clip.*/
    757                 p[i].next = &p[i + 1];
    758                 p[i].size = *(unsigned long *)((unsigned long)raw_codedbuf + next_buf_off);
    759                 p[i].buf = (unsigned char *)(((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off)) + 4); /* skip 4DWs */
    760 
    761                 if (GET_CODEDBUF_INFO(SLICE_NUM, obj_buffer->codedbuf_aux_info) <= 2 &&
    762                         GET_CODEDBUF_INFO(NONE_VCL_NUM, obj_buffer->codedbuf_aux_info) == 0) {
    763                     p[i].status =  VA_CODED_BUF_STATUS_SINGLE_NALU;
    764                     drv_debug_msg(VIDEO_DEBUG_GENERAL, "Only VCL NAL in this segment %i of coded buffer\n",
    765                             i);
    766                 }
    767                 drv_debug_msg(VIDEO_DEBUG_GENERAL, "2nd segment coded buffer offset: 0x%08x,  size: %d\n",
    768                         next_buf_off, p[i].size);
    769 
    770               i++;
    771 
    772             }
    773             /* 1st segment */
    774             p[i].size = *((unsigned long *) raw_codedbuf);
    775             p[i].buf = (unsigned char *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */
    776             drv_debug_msg(VIDEO_DEBUG_GENERAL, "1st segment coded buffer size %d\n", p[i].size);
    777             if (GET_CODEDBUF_INFO(SLICE_NUM, obj_buffer->codedbuf_aux_info) <= 2 &&
    778                     GET_CODEDBUF_INFO(NONE_VCL_NUM, obj_buffer->codedbuf_aux_info) == 0) {
    779                 p[i].status =  VA_CODED_BUF_STATUS_SINGLE_NALU;
    780                 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Only VCL NAL in this segment %i of coded buffer\n",
    781                         i);
    782             }
    783             for (i = 0; i < pnw_get_parallel_core_number(obj_context); i++) {
    784                 if (p[i].size > (next_buf_off - sizeof(unsigned long) * 4)) {
    785                     drv_debug_msg(VIDEO_DEBUG_ERROR, "Coded segment %d is too large(%d)"
    786                             " and exceed segment boundary(offset %d)", i, p[i].size, next_buf_off);
    787                     p[i].size = next_buf_off - sizeof(unsigned long) * 4;
    788                 }
    789             }
    790 
    791             break;
    792 
    793         case VAProfileH263Baseline:
    794                 /* one segment */
    795             p->size = *((unsigned long *) raw_codedbuf);
    796             p->buf = (unsigned char *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */
    797             drv_debug_msg(VIDEO_DEBUG_GENERAL, "coded buffer size %d\n", p->size);
    798             break;
    799 
    800         case VAProfileJPEGBaseline:
    801             /* 3~6 segment
    802                  */
    803             pnw_jpeg_AppendMarkers(obj_context, raw_codedbuf);
    804             next_buf_off = 0;
    805             /*Max resolution 4096x4096 use 6 segments*/
    806             for (i = 0; i < PNW_JPEG_MAX_SCAN_NUM + 1; i++) {
    807                 p->size = *(unsigned long *)((unsigned long)raw_codedbuf + next_buf_off);
    808                 p->buf = (unsigned char *)((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 4);  /* skip 4DWs */
    809                 next_buf_off = *((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 3);
    810 
    811                 drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG coded buffer segment %d size: %d\n", i, p->size);
    812                 drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG coded buffer next segment %d offset: %d\n", i + 1, next_buf_off);
    813 
    814                 if (next_buf_off == 0) {
    815                     p->next = NULL;
    816                     break;
    817                 } else
    818                     p->next = &p[1];
    819                 p++;
    820             }
    821             break;
    822 
    823         default:
    824             drv_debug_msg(VIDEO_DEBUG_ERROR, "unexpected case\n");
    825 
    826             psb_buffer_unmap(obj_buffer->psb_buffer);
    827             obj_buffer->buffer_data = NULL;
    828             break;
    829         }
    830     }
    831 #endif
    832 
    833     return 0;
    834 }
    835 
    836