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