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