/* * Copyright (c) 2011 Intel Corporation. All Rights Reserved. * Copyright (c) Imagination Technologies Limited, UK * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Waldo Bastian <waldo.bastian@intel.com> * */ #include <sys/types.h> #include "psb_buffer.h" #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <wsbm/wsbm_manager.h> #ifdef ANDROID #ifdef BAYTRAIL #include <linux/vxd_drm.h> #else #include <drm/ttm/ttm_placement.h> #include <linux/psb_drm.h> #endif #else #include <psb_drm.h> #endif #include "psb_def.h" #include "psb_drv_debug.h" #include "tng_cmdbuf.h" #ifndef BAYTRAIL #include <pnw_cmdbuf.h> #include "pnw_jpeg.h" #include "pnw_H264ES.h" #include "tng_jpegES.h" #endif #include "vsp_fw.h" /* * Create buffer */ VAStatus psb_buffer_create(psb_driver_data_p driver_data, unsigned int size, psb_buffer_type_t type, psb_buffer_p buf ) { VAStatus vaStatus = VA_STATUS_SUCCESS; int allignment; uint32_t placement; int ret; /* reset rar_handle to NULL */ buf->rar_handle = 0; buf->buffer_ofs = 0; buf->type = type; buf->driver_data = driver_data; /* only for RAR buffers */ buf->size = size; /* TODO: Mask values are a guess */ switch (type) { case psb_bt_cpu_vpu: allignment = 1; placement = DRM_PSB_FLAG_MEM_MMU; break; case psb_bt_cpu_vpu_shared: allignment = 1; placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_SHARED; break; case psb_bt_surface: allignment = 0; placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_SHARED; if (IS_CTP(driver_data)) /* CTP support cache snoop */ placement |= WSBM_PL_FLAG_CACHED; break; case psb_bt_surface_tt: allignment = 0; placement = WSBM_PL_FLAG_TT | WSBM_PL_FLAG_NO_EVICT | WSBM_PL_FLAG_SHARED; break; #ifdef PSBVIDEO_MSVDX_DEC_TILING case psb_bt_surface_tiling: drv_debug_msg(VIDEO_DEBUG_GENERAL, "Allocate tiled surface from TT heap\n"); placement = WSBM_PL_FLAG_TT | WSBM_PL_FLAG_SHARED; allignment = 2048 * 16; /* Tiled row aligned */ break; case psb_bt_mmu_tiling: placement = DRM_PSB_FLAG_MEM_MMU_TILING | WSBM_PL_FLAG_SHARED; allignment = 2048 * 16; /* Tiled row aligned */ break; #endif case psb_bt_cpu_vpu_cached: allignment = 1; placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_CACHED; break; case psb_bt_vpu_only: allignment = 1; placement = DRM_PSB_FLAG_MEM_MMU; break; case psb_bt_cpu_only: allignment = 1; placement = WSBM_PL_FLAG_SYSTEM | WSBM_PL_FLAG_CACHED; break; #if PSB_MFLD_DUMMY_CODE case psb_bt_camera: allignment = 1; placement = WSBM_PL_FLAG_SHARED; break; #endif #ifdef ANDROID #ifndef BAYTRAIL case psb_bt_imr: allignment = 1; placement = TTM_PL_FLAG_IMR | WSBM_PL_FLAG_SHARED; break; #endif #endif default: vaStatus = VA_STATUS_ERROR_UNKNOWN; DEBUG_FAILURE; return vaStatus; } ret = LOCK_HARDWARE(driver_data); if (ret) { UNLOCK_HARDWARE(driver_data); vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE_RET; return vaStatus; } #ifdef VA_EMULATOR placement |= WSBM_PL_FLAG_SHARED; #endif #ifndef ANDROID if(!(placement & WSBM_PL_FLAG_SYSTEM)) { //drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: buffer->pl_flags 0x%08x\n", __func__, placement); placement &= ~WSBM_PL_MASK_MEM; placement &= ~WSBM_PL_FLAG_NO_EVICT; placement |= TTM_PL_FLAG_VRAM; //drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: repleace buffer->pl_flags 0x%08x\n", __func__, placement); } #endif #ifdef MSVDX_VA_EMULATOR placement |= WSBM_PL_FLAG_SHARED; #endif if(allignment < 4096) allignment = 4096; /* temporily more safe */ //drv_debug_msg(VIDEO_DEBUG_ERROR, "FIXME: should use geetpagesize() ?\n"); ret = wsbmGenBuffers(driver_data->main_pool, 1, &buf->drm_buf, allignment, placement); if (!buf->drm_buf) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n"); UNLOCK_HARDWARE(driver_data); return VA_STATUS_ERROR_ALLOCATION_FAILED; } /* here use the placement when gen buffer setted */ ret = wsbmBOData(buf->drm_buf, size, NULL, NULL, 0); UNLOCK_HARDWARE(driver_data); if (ret) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc wsbm buffers\n"); return VA_STATUS_ERROR_ALLOCATION_FAILED; } if (placement & WSBM_PL_FLAG_TT) drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create BO with TT placement (%d byte),BO GPU offset hint=0x%08x\n", size, wsbmBOOffsetHint(buf->drm_buf)); buf->pl_flags = placement; buf->status = psb_bs_ready; buf->wsbm_synccpu_flag = 0; return VA_STATUS_SUCCESS; } /* * Create buffer */ VAStatus 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 ) { VAStatus vaStatus = VA_STATUS_SUCCESS; int allignment; uint32_t placement; int ret; /* reset rar_handle to NULL */ buf->rar_handle = 0; buf->buffer_ofs = 0; buf->type = type; buf->driver_data = driver_data; /* only for RAR buffers */ buf->user_ptr = vaddr; buf->fd = fd; /* Xvideo will share surface buffer, set SHARED flag */ placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_SHARED ; ret = LOCK_HARDWARE(driver_data); if (ret) { UNLOCK_HARDWARE(driver_data); vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE_RET; return vaStatus; } allignment = 4096; /* temporily more safe */ #ifdef PSBVIDEO_MSVDX_DEC_TILING if (type == psb_bt_mmu_tiling) { placement = DRM_PSB_FLAG_MEM_MMU_TILING | WSBM_PL_FLAG_SHARED ; allignment = 2048 * 16; /* Tiled row aligned */ } #endif if (flags & PSB_USER_BUFFER_WC) placement |= WSBM_PL_FLAG_WC; else if (flags & PSB_USER_BUFFER_UNCACHED) placement |= WSBM_PL_FLAG_UNCACHED; else placement |= WSBM_PL_FLAG_CACHED; //drv_debug_msg(VIDEO_DEBUG_ERROR, "FIXME: should use geetpagesize() ?\n"); ret = wsbmGenBuffers(driver_data->main_pool, 1, &buf->drm_buf, allignment, placement); if (!buf->drm_buf) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n"); UNLOCK_HARDWARE(driver_data); return VA_STATUS_ERROR_ALLOCATION_FAILED; } /* here use the placement when gen buffer setted */ drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create BO from user buffer %p, size=%d, fd = %d\n", vaddr, size, fd); ret = wsbmBODataUB(buf->drm_buf, size, NULL, NULL, 0, vaddr, fd); if (ret) { 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); UNLOCK_HARDWARE(driver_data); return 1; } drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create BO from user buffer 0x%08x (%d byte), fd=%d, BO GPU offset hint=0x%08x\n", vaddr, size, fd, wsbmBOOffsetHint(buf->drm_buf)); buf->pl_flags = placement; buf->status = psb_bs_ready; buf->wsbm_synccpu_flag = 0; UNLOCK_HARDWARE(driver_data); return VA_STATUS_SUCCESS; } #if 0 /* * buffer setstatus * * Returns 0 on success */ int psb_buffer_setstatus(psb_buffer_p buf, uint32_t set_placement, uint32_t clr_placement) { int ret = 0; ASSERT(buf); ASSERT(buf->driver_data); ret = wsbmBOSetStatus(buf->drm_buf, set_placement, clr_placement); if (ret == 0) buf->pl_flags = set_placement; return ret; } #endif VAStatus psb_buffer_reference(psb_driver_data_p driver_data, psb_buffer_p buf, psb_buffer_p reference_buf ) { int ret = 0; VAStatus vaStatus = VA_STATUS_SUCCESS; memcpy(buf, reference_buf, sizeof(*buf)); buf->drm_buf = NULL; ret = LOCK_HARDWARE(driver_data); if (ret) { UNLOCK_HARDWARE(driver_data); vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE_RET; return vaStatus; } ret = wsbmGenBuffers(driver_data->main_pool, 1, &buf->drm_buf, 4096, /* page alignment */ 0); if (!buf->drm_buf) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n"); UNLOCK_HARDWARE(driver_data); return VA_STATUS_ERROR_ALLOCATION_FAILED; } ret = wsbmBOSetReferenced(buf->drm_buf, wsbmKBufHandle(wsbmKBuf(reference_buf->drm_buf))); UNLOCK_HARDWARE(driver_data); if (ret) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc wsbm buffers\n"); return VA_STATUS_ERROR_ALLOCATION_FAILED; } return VA_STATUS_SUCCESS; } VAStatus psb_kbuffer_reference(psb_driver_data_p driver_data, psb_buffer_p buf, int kbuf_handle ) { int ret = 0; VAStatus vaStatus = VA_STATUS_SUCCESS; buf->drm_buf = NULL; ret = LOCK_HARDWARE(driver_data); if (ret) { UNLOCK_HARDWARE(driver_data); vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE_RET; return vaStatus; } ret = wsbmGenBuffers(driver_data->main_pool, 1, &buf->drm_buf, 4096, /* page alignment */ 0); if (!buf->drm_buf) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n"); UNLOCK_HARDWARE(driver_data); return VA_STATUS_ERROR_ALLOCATION_FAILED; } ret = wsbmBOSetReferenced(buf->drm_buf, kbuf_handle); UNLOCK_HARDWARE(driver_data); if (ret) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc wsbm buffers\n"); return VA_STATUS_ERROR_ALLOCATION_FAILED; } buf->pl_flags = wsbmBOPlacementHint(buf->drm_buf); buf->type = psb_bt_surface; buf->status = psb_bs_ready; return VA_STATUS_SUCCESS; } /* * Destroy buffer */ void psb_buffer_destroy(psb_buffer_p buf) { ASSERT(buf); if (buf->drm_buf == NULL) return; if (psb_bs_unfinished != buf->status) { ASSERT(buf->driver_data); wsbmBOUnreference(&buf->drm_buf); if (buf->rar_handle) buf->rar_handle = 0; buf->driver_data = NULL; buf->status = psb_bs_unfinished; } } /* * Map buffer * * Returns 0 on success */ int psb_buffer_map(psb_buffer_p buf, unsigned char **address /* out */) { int ret; ASSERT(buf); ASSERT(buf->driver_data); /* multiple mapping not allowed */ if (buf->wsbm_synccpu_flag) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "Multiple mapping request detected, unmap previous mapping\n"); drv_debug_msg(VIDEO_DEBUG_GENERAL, "Need to fix application to unmap at first, then request second mapping request\n"); psb_buffer_unmap(buf); } /* don't think TG deal with READ/WRITE differently */ buf->wsbm_synccpu_flag = WSBM_SYNCCPU_READ | WSBM_SYNCCPU_WRITE; if (psb_video_trace_fp) { wsbmBOWaitIdle(buf->drm_buf, 0); } else { ret = wsbmBOSyncForCpu(buf->drm_buf, buf->wsbm_synccpu_flag); if (ret) { drv_debug_msg(VIDEO_DEBUG_ERROR, "faild to sync bo for cpu\n"); return ret; } } if (buf->user_ptr) /* user mode buffer */ *address = buf->user_ptr; else *address = wsbmBOMap(buf->drm_buf, buf->wsbm_synccpu_flag); if (*address == NULL) { drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to map buffer\n"); return -1; } return 0; } /* * Unmap buffer * * Returns 0 on success */ int psb_buffer_unmap(psb_buffer_p buf) { ASSERT(buf); ASSERT(buf->driver_data); if (buf->wsbm_synccpu_flag) (void) wsbmBOReleaseFromCpu(buf->drm_buf, buf->wsbm_synccpu_flag); buf->wsbm_synccpu_flag = 0; if ((buf->type != psb_bt_user_buffer) && !buf->handle) wsbmBOUnmap(buf->drm_buf); return 0; } #define _MRFL_DEBUG_CODED_ #ifdef _MRFL_DEBUG_CODED_ static void psb__trace_coded(VACodedBufferSegment *vaCodedBufSeg) { int i, j; int uiPipeIndex = -1; unsigned int *pBuf = NULL; do { ++uiPipeIndex; drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: pipe num %d, size = %d\n", __FUNCTION__, uiPipeIndex, vaCodedBufSeg[uiPipeIndex].size); pBuf = (unsigned int *)(vaCodedBufSeg[uiPipeIndex].buf); pBuf -= 16; for (i = 0; i < 6; i++) { for (j = 0; j < 4; j++) { drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: 0x%08x\n", __FUNCTION__, pBuf[(i*4) + j]); } } drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s: \n", __FUNCTION__); } while (vaCodedBufSeg[uiPipeIndex].next); return ; } #endif #define PROFILE_H264(profile) ((profile>=VAProfileH264Baseline && profile <=VAProfileH264High) || \ (profile == VAProfileH264ConstrainedBaseline)) static void tng_get_coded_data( object_buffer_p obj_buffer, unsigned char *raw_codedbuf ) { object_context_p obj_context = obj_buffer->context; VACodedBufferSegment *vaCodedBufSeg = &obj_buffer->codedbuf_mapinfo[0]; int iPipeIndex = 0; unsigned int uiPipeNum = tng_get_pipe_number(obj_context); unsigned int uiBufOffset = tng_align_KB(obj_buffer->size >> 1); unsigned long *ptmp = NULL; int tmp; drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s pipenum = 0x%x\n", __FUNCTION__, uiPipeNum); drv_debug_msg(VIDEO_DEBUG_GENERAL, "%s offset = 0x%x\n", __FUNCTION__, uiBufOffset); tmp = vaCodedBufSeg[iPipeIndex].size = *(unsigned int *)((unsigned long)raw_codedbuf); /* * This is used for DRM over WiDi which only uses H264 BP * Tangier IED encryption operates on the chunks with 16bytes, and we must include * the extra bytes beyond slice data as a whole chunk for decrption * We simply include the padding bytes regardless of IED enable or disable */ if (PROFILE_H264(obj_context->profile) && (tmp % 16 != 0)) { tmp = (tmp + 15) & (~15); drv_debug_msg(VIDEO_DEBUG_GENERAL, "Force slice size from %d to %d\n", vaCodedBufSeg[iPipeIndex].size, tmp); vaCodedBufSeg[iPipeIndex].size = tmp; } vaCodedBufSeg[iPipeIndex].buf = (unsigned char *)(((unsigned int *)((unsigned long)raw_codedbuf)) + 16); /* skip 4DWs */ ptmp = (unsigned long *)((unsigned long)raw_codedbuf); vaCodedBufSeg[iPipeIndex].reserved = (ptmp[1] >> 6) & 0xf; vaCodedBufSeg[iPipeIndex].next = NULL; if (uiPipeNum == 2) { /*The second part of coded buffer which generated by core 2 is the * first part of encoded clip, while the first part of coded buffer * is the second part of encoded clip.*/ ++iPipeIndex; vaCodedBufSeg[iPipeIndex - 1].next = &vaCodedBufSeg[iPipeIndex]; tmp = vaCodedBufSeg[iPipeIndex].size = *(unsigned int *)((unsigned long)raw_codedbuf + uiBufOffset); /* * This is used for DRM over WiDi which only uses H264 BP * Tangier IED encryption operates on the chunks with 16bytes, and we must include * the extra bytes beyond slice data as a whole chunk for decryption * We simply include the padding bytes regardless of IED enable or disable */ if (PROFILE_H264(obj_context->profile) && (tmp % 16 != 0)) { tmp = (tmp + 15) & (~15); drv_debug_msg(VIDEO_DEBUG_GENERAL,"Force slice size from %d to %d\n", vaCodedBufSeg[iPipeIndex].size, tmp); vaCodedBufSeg[iPipeIndex].size = tmp; } vaCodedBufSeg[iPipeIndex].buf = (unsigned char *)(((unsigned int *)((unsigned long)raw_codedbuf + uiBufOffset)) + 16); /* skip 4DWs */ vaCodedBufSeg[iPipeIndex].reserved = vaCodedBufSeg[iPipeIndex - 1].reserved; vaCodedBufSeg[iPipeIndex].next = NULL; } #ifdef _MRFL_DEBUG_CODED_ psb__trace_coded(vaCodedBufSeg); #endif return ; } /* * Return special data structure for codedbuffer * * Returns 0 on success */ #define CONFIG(id) ((object_config_p) object_heap_lookup( &driver_data->config_heap, id )) #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData; int psb_codedbuf_map_mangle( VADriverContextP ctx, object_buffer_p obj_buffer, void **pbuf /* out */ ) { object_context_p obj_context = obj_buffer->context; INIT_DRIVER_DATA; VACodedBufferSegment *p = &obj_buffer->codedbuf_mapinfo[0]; unsigned char *raw_codedbuf; VAStatus vaStatus = VA_STATUS_SUCCESS; unsigned int next_buf_off; uint32_t i; CHECK_INVALID_PARAM(pbuf == NULL); if (NULL == obj_context) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; psb_buffer_unmap(obj_buffer->psb_buffer); obj_buffer->buffer_data = NULL; return vaStatus; } raw_codedbuf = *pbuf; /* reset the mapinfo */ memset(obj_buffer->codedbuf_mapinfo, 0, sizeof(obj_buffer->codedbuf_mapinfo)); *pbuf = p = &obj_buffer->codedbuf_mapinfo[0]; #ifdef PSBVIDEO_MRFL if (IS_MRFL(driver_data)) { object_config_p obj_config = CONFIG(obj_context->config_id); if (NULL == obj_config) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; psb_buffer_unmap(obj_buffer->psb_buffer); obj_buffer->buffer_data = NULL; return vaStatus; } if (VAProfileJPEGBaseline != obj_config->profile && (*((unsigned long *) raw_codedbuf + 1) & SKIP_NEXT_FRAME) != 0) { /*Set frame skip flag*/ tng_set_frame_skip_flag(obj_context); } switch (obj_config->profile) { case VAProfileMPEG4Simple: case VAProfileMPEG4AdvancedSimple: case VAProfileMPEG4Main: case VAProfileH264Baseline: case VAProfileH264Main: case VAProfileH264High: case VAProfileH264StereoHigh: case VAProfileH264ConstrainedBaseline: case VAProfileH263Baseline: /* 1st segment */ tng_get_coded_data(obj_buffer, raw_codedbuf); #if 0 p->size = *((unsigned long *) raw_codedbuf); p->buf = (unsigned char *)((unsigned long *) raw_codedbuf + 16); /* skip 16DWs */ p->next = NULL; #ifdef _MRFL_DEBUG_CODED_ psb__trace_coded((unsigned int*)raw_codedbuf); psb__trace_coded(p); #endif #endif break; case VAProfileVP8Version0_3: { /* multi segments*/ struct VssVp8encEncodedFrame *t = (struct VssVp8encEncodedFrame *) (raw_codedbuf); int concatenate = 1; #if 0 for (i = 0; i < t->partitions - 1; i++) { if (t->partition_start[i+1] != t->partition_start[i] + t->partition_size[i]) concatenate = 0; } #endif /* reference frame surface_id */ /* default is recon_buffer_mode ==0 */ p->reserved = t->surfaceId_of_ref_frame[3]; if (concatenate) { /* partitions are concatenate */ p->buf = t->coded_data; p->size = t->frame_size; if(t->frame_size == 0){ drv_debug_msg(VIDEO_DEBUG_ERROR,"Frame size is zero, Force it to 3, encoder status is 0x%x\n", t->status); p->size = 3; t->coded_data[0]=0; } p->next = NULL; } else { for (i = 0; i < t->partitions; i++) { /* partition not consecutive */ p->buf = t->coded_data + t->partition_start[i] - t->partition_start[0]; p->size += t->partition_size[i]; p->next = &p[1]; p++; } p--; p->next = NULL; } break; } case VAProfileJPEGBaseline: /* 3~6 segment */ tng_jpeg_AppendMarkers(obj_context, raw_codedbuf); next_buf_off = 0; /*Max resolution 4096x4096 use 6 segments*/ for (i = 0; i < PTG_JPEG_MAX_SCAN_NUM + 1; i++) { p->size = *(unsigned long *)((unsigned long)raw_codedbuf + next_buf_off); /* ui32BytesUsed in HEADER_BUFFER*/ p->buf = (unsigned char *)((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 4); /* skip 4DWs (HEADER_BUFFER) */ next_buf_off = *((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 3); /* ui32Reserved3 in HEADER_BUFFER*/ drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG coded buffer segment %d size: %d\n", i, p->size); drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG coded buffer next segment %d offset: %d\n", i + 1, next_buf_off); if (next_buf_off == 0) { p->next = NULL; break; } else p->next = &p[1]; p++; } break; default: drv_debug_msg(VIDEO_DEBUG_ERROR, "unexpected case\n"); psb_buffer_unmap(obj_buffer->psb_buffer); obj_buffer->buffer_data = NULL; break; } } #endif #ifdef PSBVIDEO_MFLD if (IS_MFLD(driver_data)){ /* MFLD */ object_config_p obj_config = CONFIG(obj_context->config_id); if (NULL == obj_config) { vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; DEBUG_FAILURE; psb_buffer_unmap(obj_buffer->psb_buffer); obj_buffer->buffer_data = NULL; return vaStatus; } if (VAProfileJPEGBaseline != obj_config->profile && (*((unsigned long *) raw_codedbuf + 1) & SKIP_NEXT_FRAME) != 0) { /*Set frame skip flag*/ pnw_set_frame_skip_flag(obj_context); } switch (obj_config->profile) { case VAProfileMPEG4Simple: case VAProfileMPEG4AdvancedSimple: case VAProfileMPEG4Main: /* one segment */ p->size = *((unsigned long *) raw_codedbuf); p->buf = (unsigned char *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */ drv_debug_msg(VIDEO_DEBUG_GENERAL, "coded buffer size %d\n", p->size); break; case VAProfileH264Baseline: case VAProfileH264Main: case VAProfileH264High: case VAProfileH264ConstrainedBaseline: i = 0; next_buf_off = ~0xf & (obj_buffer->size / pnw_get_parallel_core_number(obj_context)); if (pnw_get_parallel_core_number(obj_context) == 2) { /*The second part of coded buffer which generated by core 2 is the * first part of encoded clip, while the first part of coded buffer * is the second part of encoded clip.*/ p[i].next = &p[i + 1]; p[i].size = *(unsigned long *)((unsigned long)raw_codedbuf + next_buf_off); p[i].buf = (unsigned char *)(((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off)) + 4); /* skip 4DWs */ if (GET_CODEDBUF_INFO(SLICE_NUM, obj_buffer->codedbuf_aux_info) <= 2 && GET_CODEDBUF_INFO(NONE_VCL_NUM, obj_buffer->codedbuf_aux_info) == 0) { p[i].status = VA_CODED_BUF_STATUS_SINGLE_NALU; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Only VCL NAL in this segment %i of coded buffer\n", i); } drv_debug_msg(VIDEO_DEBUG_GENERAL, "2nd segment coded buffer offset: 0x%08x, size: %d\n", next_buf_off, p[i].size); i++; } /* 1st segment */ p[i].size = *((unsigned long *) raw_codedbuf); p[i].buf = (unsigned char *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */ drv_debug_msg(VIDEO_DEBUG_GENERAL, "1st segment coded buffer size %d\n", p[i].size); if (GET_CODEDBUF_INFO(SLICE_NUM, obj_buffer->codedbuf_aux_info) <= 2 && GET_CODEDBUF_INFO(NONE_VCL_NUM, obj_buffer->codedbuf_aux_info) == 0) { p[i].status = VA_CODED_BUF_STATUS_SINGLE_NALU; drv_debug_msg(VIDEO_DEBUG_GENERAL, "Only VCL NAL in this segment %i of coded buffer\n", i); } for (i = 0; i < pnw_get_parallel_core_number(obj_context); i++) { if (p[i].size > (next_buf_off - sizeof(unsigned long) * 4)) { drv_debug_msg(VIDEO_DEBUG_ERROR, "Coded segment %d is too large(%d)" " and exceed segment boundary(offset %d)", i, p[i].size, next_buf_off); p[i].size = next_buf_off - sizeof(unsigned long) * 4; } } break; case VAProfileH263Baseline: /* one segment */ p->size = *((unsigned long *) raw_codedbuf); p->buf = (unsigned char *)((unsigned long *) raw_codedbuf + 4); /* skip 4DWs */ drv_debug_msg(VIDEO_DEBUG_GENERAL, "coded buffer size %d\n", p->size); break; case VAProfileJPEGBaseline: /* 3~6 segment */ pnw_jpeg_AppendMarkers(obj_context, raw_codedbuf); next_buf_off = 0; /*Max resolution 4096x4096 use 6 segments*/ for (i = 0; i < PNW_JPEG_MAX_SCAN_NUM + 1; i++) { p->size = *(unsigned long *)((unsigned long)raw_codedbuf + next_buf_off); p->buf = (unsigned char *)((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 4); /* skip 4DWs */ next_buf_off = *((unsigned long *)((unsigned long)raw_codedbuf + next_buf_off) + 3); drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG coded buffer segment %d size: %d\n", i, p->size); drv_debug_msg(VIDEO_DEBUG_GENERAL, "JPEG coded buffer next segment %d offset: %d\n", i + 1, next_buf_off); if (next_buf_off == 0) { p->next = NULL; break; } else p->next = &p[1]; p++; } break; default: drv_debug_msg(VIDEO_DEBUG_ERROR, "unexpected case\n"); psb_buffer_unmap(obj_buffer->psb_buffer); obj_buffer->buffer_data = NULL; break; } } #endif return 0; }