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