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@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 */
64VAStatus 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 */
204VAStatus 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 */
290int 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
305VAStatus 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
345VAStatus 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 */
389void 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 */
409int 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 */
454int 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_
473static 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))
497static 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;
576int 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