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  */
psb_buffer_create(psb_driver_data_p driver_data,unsigned int size,psb_buffer_type_t type,psb_buffer_p buf)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  */
psb_buffer_create_from_ub(psb_driver_data_p driver_data,unsigned int size,psb_buffer_type_t type,psb_buffer_p buf,void * vaddr,int fd,unsigned int flags)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 
psb_buffer_reference(psb_driver_data_p driver_data,psb_buffer_p buf,psb_buffer_p reference_buf)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 
psb_kbuffer_reference(psb_driver_data_p driver_data,psb_buffer_p buf,int kbuf_handle)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  */
psb_buffer_destroy(psb_buffer_p buf)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  */
psb_buffer_map(psb_buffer_p buf,unsigned char ** address)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  */
psb_buffer_unmap(psb_buffer_p buf)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_
psb__trace_coded(VACodedBufferSegment * vaCodedBufSeg)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))
tng_get_coded_data(object_buffer_p obj_buffer,unsigned char * raw_codedbuf)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;
psb_codedbuf_map_mangle(VADriverContextP ctx,object_buffer_p obj_buffer,void ** pbuf)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