psb_buffer.c revision c3077df94073dd4c035f86e5f1428e4611a0cf73
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 "psb_buffer.h" 31 32#include <errno.h> 33#include <stdlib.h> 34#include <unistd.h> 35#include <wsbm/wsbm_manager.h> 36 37#include "psb_drm.h" 38#include "psb_def.h" 39 40#include <pnw_cmdbuf.h> 41 42#include "pnw_jpeg.h" 43#include "pnw_H264ES.h" 44#include "lnc_H264ES.h" 45 46/* 47 * Create buffer 48 */ 49VAStatus psb_buffer_create(psb_driver_data_p driver_data, 50 unsigned int size, 51 psb_buffer_type_t type, 52 psb_buffer_p buf 53 ) 54{ 55 VAStatus vaStatus = VA_STATUS_SUCCESS; 56 int allignment; 57 uint32_t placement; 58 int ret; 59 60 /* reset rar_handle to NULL */ 61 buf->rar_handle = 0; 62 buf->buffer_ofs = 0; 63 64 buf->type = type; 65 buf->driver_data = driver_data; /* only for RAR buffers */ 66 67 /* TODO: Mask values are a guess */ 68 switch (type) { 69 case psb_bt_cpu_vpu: 70 allignment = 1; 71 placement = DRM_PSB_FLAG_MEM_MMU; 72 break; 73 case psb_bt_cpu_vpu_shared: 74 allignment = 1; 75 placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_SHARED; 76 break; 77 case psb_bt_surface: 78 allignment = 0; 79 /* Xvideo will share surface buffer, set SHARED flag 80 */ 81 if (getenv("PSB_VIDEO_SURFACE_MMU")) { 82 psb__information_message("Allocate surface from MMU heap\n"); 83 placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_SHARED; 84 } else { 85 psb__information_message("Allocate surface from TT heap\n"); 86 placement = WSBM_PL_FLAG_TT | WSBM_PL_FLAG_SHARED; 87 } 88 break; 89 case psb_bt_vpu_only: 90 allignment = 1; 91 placement = DRM_PSB_FLAG_MEM_MMU; 92 break; 93 94 case psb_bt_cpu_only: 95 allignment = 1; 96 placement = WSBM_PL_FLAG_SYSTEM | WSBM_PL_FLAG_CACHED; 97 break; 98 case psb_bt_camera: 99 allignment = 1; 100 placement = TTM_PL_FLAG_CI | WSBM_PL_FLAG_SHARED; 101 break; 102 case psb_bt_rar: 103 allignment = 1; 104 placement = TTM_PL_FLAG_RAR | WSBM_PL_FLAG_SHARED; 105 break; 106 default: 107 vaStatus = VA_STATUS_ERROR_UNKNOWN; 108 DEBUG_FAILURE; 109 return vaStatus; 110 } 111 ret = LOCK_HARDWARE(driver_data); 112 if (ret) { 113 UNLOCK_HARDWARE(driver_data); 114 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 115 DEBUG_FAILURE_RET; 116 return vaStatus; 117 } 118 119#ifdef VA_EMULATOR 120 placement |= WSBM_PL_FLAG_SHARED; 121#endif 122 123#ifdef MSVDX_VA_EMULATOR 124 placement |= WSBM_PL_FLAG_SHARED; 125#endif 126 127 allignment = 4096; /* temporily more safe */ 128 129 //psb__error_message("FIXME: should use geetpagesize() ?\n"); 130 ret = wsbmGenBuffers(driver_data->main_pool, 1, &buf->drm_buf, 131 allignment, placement); 132 if (!buf->drm_buf) { 133 psb__error_message("failed to gen wsbm buffers\n"); 134 UNLOCK_HARDWARE(driver_data); 135 return VA_STATUS_ERROR_ALLOCATION_FAILED; 136 } 137 138 /* here use the placement when gen buffer setted */ 139 ret = wsbmBOData(buf->drm_buf, size, NULL, NULL, 0); 140 UNLOCK_HARDWARE(driver_data); 141 if (ret) { 142 psb__error_message("failed to alloc wsbm buffers\n"); 143 return VA_STATUS_ERROR_ALLOCATION_FAILED; 144 } 145 146 if (placement & WSBM_PL_FLAG_TT) 147 psb__information_message("Create BO with TT placement (%d byte),BO GPU offset hint=0x%08x\n", 148 size, wsbmBOOffsetHint(buf->drm_buf)); 149 150 buf->pl_flags = placement; 151 buf->status = psb_bs_ready; 152 buf->wsbm_synccpu_flag = 0; 153 154 return VA_STATUS_SUCCESS; 155} 156 157 158/* 159 * buffer setstatus 160 * 161 * Returns 0 on success 162 */ 163int psb_buffer_setstatus(psb_buffer_p buf, uint32_t set_placement, uint32_t clr_placement) 164{ 165 int ret = 0; 166 167 ASSERT(buf); 168 ASSERT(buf->driver_data); 169 170 ret = wsbmBOSetStatus(buf->drm_buf, set_placement, clr_placement); 171 if (ret == 0) 172 buf->pl_flags = set_placement; 173 174 return ret; 175} 176 177 178VAStatus psb_buffer_reference(psb_driver_data_p driver_data, 179 psb_buffer_p buf, 180 psb_buffer_p reference_buf 181 ) 182{ 183 int ret = 0; 184 VAStatus vaStatus = VA_STATUS_SUCCESS; 185 186 memcpy(buf, reference_buf, sizeof(*buf)); 187 buf->drm_buf = NULL; 188 189 ret = LOCK_HARDWARE(driver_data); 190 if (ret) { 191 UNLOCK_HARDWARE(driver_data); 192 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 193 DEBUG_FAILURE_RET; 194 return vaStatus; 195 } 196 197 ret = wsbmGenBuffers(driver_data->main_pool, 198 1, 199 &buf->drm_buf, 200 4096, /* page alignment */ 201 0); 202 if (!buf->drm_buf) { 203 psb__error_message("failed to gen wsbm buffers\n"); 204 UNLOCK_HARDWARE(driver_data); 205 return VA_STATUS_ERROR_ALLOCATION_FAILED; 206 } 207 208 ret = wsbmBOSetReferenced(buf->drm_buf, wsbmKBufHandle(wsbmKBuf(reference_buf->drm_buf))); 209 UNLOCK_HARDWARE(driver_data); 210 if (ret) { 211 psb__error_message("failed to alloc wsbm buffers\n"); 212 return VA_STATUS_ERROR_ALLOCATION_FAILED; 213 } 214 215 return VA_STATUS_SUCCESS; 216} 217 218VAStatus psb_kbuffer_reference(psb_driver_data_p driver_data, 219 psb_buffer_p buf, 220 int kbuf_handle 221 ) 222{ 223 int ret = 0; 224 VAStatus vaStatus = VA_STATUS_SUCCESS; 225 226 buf->drm_buf = NULL; 227 228 ret = LOCK_HARDWARE(driver_data); 229 if (ret) { 230 UNLOCK_HARDWARE(driver_data); 231 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 232 DEBUG_FAILURE_RET; 233 return vaStatus; 234 } 235 236 ret = wsbmGenBuffers(driver_data->main_pool, 237 1, 238 &buf->drm_buf, 239 4096, /* page alignment */ 240 0); 241 if (!buf->drm_buf) { 242 psb__error_message("failed to gen wsbm buffers\n"); 243 UNLOCK_HARDWARE(driver_data); 244 return VA_STATUS_ERROR_ALLOCATION_FAILED; 245 } 246 247 ret = wsbmBOSetReferenced(buf->drm_buf,kbuf_handle ); 248 UNLOCK_HARDWARE(driver_data); 249 if (ret) { 250 psb__error_message("failed to alloc wsbm buffers\n"); 251 return VA_STATUS_ERROR_ALLOCATION_FAILED; 252 } 253 buf->pl_flags = wsbmBOPlacementHint(buf->drm_buf); 254 255 return VA_STATUS_SUCCESS; 256} 257/* 258 * Destroy buffer 259 */ 260void psb_buffer_destroy(psb_buffer_p buf) 261{ 262 ASSERT(buf); 263 if (buf->drm_buf == NULL) 264 return; 265 if (psb_bs_unfinished != buf->status) { 266 ASSERT(buf->driver_data); 267 wsbmBOUnreference(&buf->drm_buf); 268 if (buf->rar_handle) 269 buf->rar_handle = 0; 270 buf->driver_data = NULL; 271 buf->status = psb_bs_unfinished; 272 } 273} 274 275/* 276 * Map buffer 277 * 278 * Returns 0 on success 279 */ 280int psb_buffer_map(psb_buffer_p buf, void **address /* out */) 281{ 282 int ret; 283 284 ASSERT(buf); 285 ASSERT(buf->driver_data); 286 287 /* multiple mapping not allowed */ 288 if (buf->wsbm_synccpu_flag) { 289 psb__information_message("Multiple mapping request detected, unmap previous mapping\n"); 290 psb__information_message("Need to fix application to unmap at first, then request second mapping request\n"); 291 292 psb_buffer_unmap(buf); 293 } 294 295 /* don't think TG deal with READ/WRITE differently */ 296 buf->wsbm_synccpu_flag = WSBM_SYNCCPU_READ | WSBM_SYNCCPU_WRITE; 297#ifdef DEBUG_TRACE 298 wsbmBOWaitIdle(buf->drm_buf, 0); 299#else 300 ret = wsbmBOSyncForCpu(buf->drm_buf, buf->wsbm_synccpu_flag); 301 if (ret) { 302 psb__error_message("faild to sync bo for cpu\n"); 303 return ret; 304 } 305#endif 306 307 if (buf->type == psb_bt_user_buffer) 308 *address = buf->user_ptr; 309 else 310 *address = wsbmBOMap(buf->drm_buf, buf->wsbm_synccpu_flag); 311 312 if (*address == NULL) { 313 psb__error_message("failed to map buffer\n"); 314 return -1; 315 } 316 317 return 0; 318 319} 320 321/* 322 * Unmap buffer 323 * 324 * Returns 0 on success 325 */ 326int psb_buffer_unmap(psb_buffer_p buf) 327{ 328 ASSERT(buf); 329 ASSERT(buf->driver_data); 330 331 if (buf->wsbm_synccpu_flag) 332 (void) wsbmBOReleaseFromCpu(buf->drm_buf, buf->wsbm_synccpu_flag); 333 334 buf->wsbm_synccpu_flag = 0; 335 336 if (buf->type != psb_bt_user_buffer) 337 wsbmBOUnmap(buf->drm_buf); 338 339 return 0; 340} 341 342 343/* 344 * Return special data structure for codedbuffer 345 * 346 * Returns 0 on success 347 */ 348#define CONFIG(id) ((object_config_p) object_heap_lookup( &driver_data->config_heap, id )) 349#define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData; 350int psb_codedbuf_map_mangle( 351 VADriverContextP ctx, 352 object_buffer_p obj_buffer, 353 void **pbuf /* out */ 354) 355{ 356 object_context_p obj_context = obj_buffer->context; 357 INIT_DRIVER_DATA; 358 VACodedBufferSegment *p = &obj_buffer->codedbuf_mapinfo[0]; 359 void *raw_codedbuf; 360 VAStatus vaStatus = VA_STATUS_SUCCESS; 361 unsigned int next_buf_off; 362 int i; 363 364 if (NULL == pbuf) { 365 vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER; 366 return vaStatus; 367 } 368 369 if (NULL == obj_context) { 370 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 371 DEBUG_FAILURE; 372 373 psb_buffer_unmap(obj_buffer->psb_buffer); 374 obj_buffer->buffer_data = NULL; 375 376 return vaStatus; 377 } 378 379 raw_codedbuf = *pbuf; 380 /* reset the mapinfo */ 381 memset(obj_buffer->codedbuf_mapinfo, 0, sizeof(obj_buffer->codedbuf_mapinfo)); 382 383 *pbuf = p = &obj_buffer->codedbuf_mapinfo[0]; 384 if (IS_MRST(driver_data)) { 385 /* one segment */ 386 p->size = *((unsigned long *) raw_codedbuf); /* 1st DW is the size */ 387 p->status = *((unsigned long *) raw_codedbuf + 1); /* 2nd DW 388 * is rc status */ 389 p->reserved = 0; 390 p->buf = (void *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */ 391 lnc_H264_append_aux_info(obj_context, 392 obj_buffer, 393 (unsigned char *)p->buf, 394 &(p->size)); 395 } else { /* MFLD */ 396 object_config_p obj_config = CONFIG(obj_context->config_id); 397 398 if (NULL == obj_config) { 399 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 400 DEBUG_FAILURE; 401 402 psb_buffer_unmap(obj_buffer->psb_buffer); 403 obj_buffer->buffer_data = NULL; 404 405 return vaStatus; 406 } 407 408 if (VAProfileJPEGBaseline != obj_config->profile 409 && (*((unsigned long *) raw_codedbuf + 1) & SKIP_NEXT_FRAME) != 0) { 410 /*Set frame skip flag*/ 411 pnw_set_frame_skip_flag(obj_context); 412 } 413 switch (obj_config->profile) { 414 case VAProfileMPEG4Simple: 415 case VAProfileMPEG4AdvancedSimple: 416 case VAProfileMPEG4Main: 417 /* one segment */ 418 p->size = *((unsigned long *) raw_codedbuf); 419 p->buf = (void *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */ 420 psb__information_message("coded buffer size %d\n", p->size); 421 break; 422 423 case VAProfileH264Baseline: 424 case VAProfileH264Main: 425 case VAProfileH264High: 426 case VAProfileH264ConstrainedBaseline: 427 /* 1st segment */ 428 p->size = *((unsigned long *) raw_codedbuf); 429 p->buf = (void *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */ 430 431 psb__information_message("1st segment coded buffer size %d\n", p->size); 432 if (pnw_get_parallel_core_number(obj_context) == 2) { 433 /*The second part of coded buffer which generated by core 2 is the 434 * first part of encoded clip, while the first part of coded buffer 435 * is the second part of encoded clip.*/ 436 next_buf_off = ~0xf & (obj_buffer->size / pnw_get_parallel_core_number(obj_context)); 437 p->next = &p[1]; 438 p[1].size = p->size; 439 p[1].buf = p->buf; 440 p[1].next = NULL; 441 p->size = *(unsigned long *)((unsigned long)raw_codedbuf + next_buf_off); 442 p->buf = (void *)(((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off)) + 4); /* skip 4DWs */ 443 psb__information_message("2nd segment coded buffer offset: 0x%08x, size: %d\n", 444 next_buf_off, p->size); 445 } else 446 p->next = NULL; 447 break; 448 449 case VAProfileH263Baseline: 450 /* one segment */ 451 p->size = *((unsigned long *) raw_codedbuf); 452 p->buf = (void *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */ 453 psb__information_message("coded buffer size %d\n", p->size); 454 break; 455 456 case VAProfileJPEGBaseline: 457 /* 3~6 segment 458 */ 459 pnw_jpeg_AppendMarkers(obj_context, raw_codedbuf); 460 next_buf_off = 0; 461 /*Max resolution 4096x4096 use 6 segments*/ 462 for (i = 0; i < PNW_JPEG_MAX_SCAN_NUM + 1; i++) { 463 p->size = *(unsigned long *)((unsigned long)raw_codedbuf + next_buf_off); 464 p->buf = (void *)((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 4); /* skip 4DWs */ 465 next_buf_off = *((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 3); 466 467 psb__information_message("JPEG coded buffer segment %d size: %d\n", i, p->size); 468 psb__information_message("JPEG coded buffer next segment %d offset: %d\n", i + 1, next_buf_off); 469 470 if (next_buf_off == 0) { 471 p->next = NULL; 472 break; 473 } else 474 p->next = &p[1]; 475 p++; 476 } 477 break; 478 479 default: 480 psb__error_message("unexpected case\n"); 481 482 psb_buffer_unmap(obj_buffer->psb_buffer); 483 obj_buffer->buffer_data = NULL; 484 break; 485 } 486 } 487 488 return 0; 489} 490 491int psb_buffer_sync(psb_buffer_p buf) 492{ 493 int ret; 494 495 ASSERT(buf); 496 ASSERT(buf->driver_data); 497 498 ret = wsbmBOSyncForCpu(buf->drm_buf, buf->wsbm_synccpu_flag); 499 if (ret) { 500 psb__error_message("faild to sync bo for cpu\n"); 501 return VA_STATUS_ERROR_UNKNOWN; 502 } 503 504 return VA_STATUS_SUCCESS; 505} 506