psb_buffer_dm.c revision cc2673c315517dd5a4bd294fb8707cf40c0d2088
1/* 2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sub license, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the 13 * next paragraph) shall be included in all copies or substantial portions 14 * of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Shengquan Yuan <shengquan.yuan@intel.com> 26 * Forrest Zhang <forrest.zhang@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_def.h" 38#include "psb_drv_debug.h" 39 40static VAStatus psb_buffer_offset_camerav4l2(psb_driver_data_p driver_data, 41 psb_buffer_p buf, 42 unsigned int v4l2_buf_offset, 43 unsigned int *bo_offset 44 ) 45{ 46 *bo_offset = v4l2_buf_offset; 47 return VA_STATUS_SUCCESS; 48} 49 50 51static VAStatus psb_buffer_offset_cameraci(psb_driver_data_p driver_data, 52 psb_buffer_p buf, 53 unsigned int ci_frame_offset_or_handle, 54 unsigned int *bo_offset 55 ) 56{ 57 *bo_offset = ci_frame_offset_or_handle; 58 59 return VA_STATUS_SUCCESS; 60} 61 62 63static int psb_buffer_info_ci(psb_driver_data_p driver_data) 64{ 65 struct drm_lnc_video_getparam_arg arg; 66 unsigned long camera_info[2] = {0, 0}; 67 int ret = 0; 68 69 driver_data->camera_phyaddr = driver_data->camera_size = 0; 70 71 arg.key = LNC_VIDEO_GETPARAM_CI_INFO; 72 arg.value = (uint64_t)((unsigned long) & camera_info[0]); 73 ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, 74 &arg, sizeof(arg)); 75 if (ret == 0) { 76 driver_data->camera_phyaddr = camera_info[0]; 77 driver_data->camera_size = camera_info[1]; 78 drv_debug_msg(VIDEO_DEBUG_GENERAL, "CI region physical address = 0x%08x, size=%dK\n", 79 driver_data->camera_phyaddr, driver_data->camera_size / 1024); 80 81 return ret; 82 } 83 84 drv_debug_msg(VIDEO_DEBUG_GENERAL, "CI region get_info failed\n"); 85 return ret; 86} 87 88/* 89 * Allocate global BO which maps camear device memory as encode MMU memory 90 * the global BO shared by several encode surfaces created from camear memory 91 */ 92static VAStatus psb_buffer_init_camera(psb_driver_data_p driver_data) 93{ 94 int ret = 0; 95 96 /* hasn't grab camera device memory region 97 * grab the whole 4M camera device memory 98 */ 99 driver_data->camera_bo = calloc(1, sizeof(struct psb_buffer_s)); 100 if (driver_data->camera_bo == NULL) 101 return VA_STATUS_ERROR_ALLOCATION_FAILED; 102 103 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Grab whole camera device memory\n"); 104 ret = psb_buffer_create(driver_data, driver_data->camera_size, psb_bt_camera, (psb_buffer_p) driver_data->camera_bo); 105 106 if (ret != VA_STATUS_SUCCESS) { 107 free(driver_data->camera_bo); 108 driver_data->camera_bo = NULL; 109 110 drv_debug_msg(VIDEO_DEBUG_ERROR, "Grab camera device memory failed\n"); 111 } 112 113 return ret; 114} 115 116 117/* 118 * Create one buffer from camera device memory 119 * is_v4l2 means if the buffer is V4L2 buffer 120 * id_or_ofs is CI frame ID (actually now is frame offset), or V4L2 buffer offset 121 */ 122VAStatus psb_buffer_create_camera(psb_driver_data_p driver_data, 123 psb_buffer_p buf, 124 int is_v4l2, 125 int id_or_ofs 126 ) 127{ 128 VAStatus vaStatus; 129 int ret = 0; 130 unsigned int camera_offset = 0; 131 132 if (driver_data->camera_bo == NULL) { 133 if (psb_buffer_info_ci(driver_data)) { 134 drv_debug_msg(VIDEO_DEBUG_ERROR, "Can't get CI region information\n"); 135 return VA_STATUS_ERROR_UNKNOWN; 136 } 137 138 vaStatus = psb_buffer_init_camera(driver_data); 139 if (vaStatus != VA_STATUS_SUCCESS) { 140 drv_debug_msg(VIDEO_DEBUG_ERROR, "Grab camera device memory failed\n"); 141 return ret; 142 } 143 } 144 145 /* reference the global camear BO */ 146 ret = psb_buffer_reference(driver_data, buf, (psb_buffer_p) driver_data->camera_bo); 147 if (ret != VA_STATUS_SUCCESS) { 148 drv_debug_msg(VIDEO_DEBUG_ERROR, "Reference camera device memory failed\n"); 149 return ret; 150 } 151 152 if (is_v4l2) 153 ret = psb_buffer_offset_camerav4l2(driver_data, buf, id_or_ofs, &camera_offset); 154 else 155 ret = psb_buffer_offset_cameraci(driver_data, buf, id_or_ofs, &camera_offset); 156 157 buf->buffer_ofs = camera_offset; 158 159 return ret; 160} 161 162/* 163 * Create one buffer from user buffer 164 * id_or_ofs is CI frame ID (actually now is frame offset), or V4L2 buffer offset 165 * user_ptr :virtual address of user buffer start. 166 */ 167VAStatus psb_buffer_create_camera_from_ub(psb_driver_data_p driver_data, 168 psb_buffer_p buf, 169 int id_or_ofs, 170 int size, 171 const unsigned long * user_ptr) 172{ 173 VAStatus vaStatus = VA_STATUS_SUCCESS; 174 int allignment; 175 uint32_t placement; 176 int ret; 177 178 buf->rar_handle = 0; 179 buf->buffer_ofs = 0; 180 buf->type = psb_bt_user_buffer; 181 buf->user_ptr = (unsigned char *)user_ptr; 182 buf->driver_data = driver_data; 183 184 allignment = 4096; 185 placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_TT | WSBM_PL_FLAG_CACHED | WSBM_PL_FLAG_SHARED ; 186 ret = LOCK_HARDWARE(driver_data); 187 if (ret) { 188 UNLOCK_HARDWARE(driver_data); 189 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 190 DEBUG_FAILURE_RET; 191 return vaStatus; 192 } 193 ret = wsbmGenBuffers(driver_data->main_pool, 1, &buf->drm_buf, 194 allignment, placement); 195 if (!buf->drm_buf) { 196 drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n"); 197 UNLOCK_HARDWARE(driver_data); 198 return VA_STATUS_ERROR_ALLOCATION_FAILED; 199 } 200 201 /* here use the placement when gen buffer setted */ 202 ret = wsbmBODataUB(buf->drm_buf, size, NULL, NULL, 0, user_ptr); 203 UNLOCK_HARDWARE(driver_data); 204 if (ret) { 205 drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc wsbm buffers\n"); 206 return VA_STATUS_ERROR_ALLOCATION_FAILED; 207 } 208 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create BO from user buffer 0x%08x (%d byte),BO GPU offset hint=0x%08x\n", 209 user_ptr, size, wsbmBOOffsetHint(buf->drm_buf)); 210 211 212 buf->pl_flags = placement; 213 buf->status = psb_bs_ready; 214 buf->wsbm_synccpu_flag = 0; 215 216 return VA_STATUS_SUCCESS; 217} 218 219static int psb_buffer_info_rar(psb_driver_data_p driver_data) 220{ 221 struct drm_lnc_video_getparam_arg arg; 222 unsigned long rar_info[2] = {0, 0}; 223 int ret = 0; 224 225 driver_data->rar_phyaddr = driver_data->rar_size = 0; 226 227 arg.key = LNC_VIDEO_GETPARAM_IMR_INFO; 228 arg.value = (uint64_t)((unsigned long) & rar_info[0]); 229 ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, 230 &arg, sizeof(arg)); 231 if (ret == 0) { 232 driver_data->rar_phyaddr = rar_info[0]; 233 driver_data->rar_size = rar_info[1]; 234 driver_data->rar_size = driver_data->rar_size & 0xfffff000; /* page align */ 235 drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR region physical address = 0x%08x, size=%dK\n", 236 driver_data->rar_phyaddr, driver_data->rar_size / 1024); 237 238 return ret; 239 } 240 241 drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR region get size failed\n"); 242 return ret; 243} 244 245 246static VAStatus psb_buffer_init_imr(psb_driver_data_p driver_data) 247{ 248 int ret = 0; 249 250 /* hasn't grab IMR device memory region 251 * grab the whole IMR3 device memory 252 */ 253 driver_data->rar_bo = calloc(1, sizeof(struct psb_buffer_s)); 254 if (driver_data->rar_bo == NULL) 255 goto exit_error; 256 257 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Init IMR device\n"); 258 if (psb_buffer_info_rar(driver_data)) { 259 drv_debug_msg(VIDEO_DEBUG_ERROR, "Get IMR region size failed\n"); 260 goto exit_error; 261 } 262 263 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Grab whole camera device memory\n"); 264 ret = psb_buffer_create(driver_data, driver_data->rar_size, psb_bt_imr, (psb_buffer_p) driver_data->rar_bo); 265 266 if (ret != VA_STATUS_SUCCESS) { 267 drv_debug_msg(VIDEO_DEBUG_ERROR, "Grab IMR device memory failed\n"); 268 goto exit_error; 269 } 270 271 return VA_STATUS_SUCCESS; 272 273exit_error: 274 if (driver_data->rar_bo) 275 free(driver_data->rar_bo); 276 277 driver_data->rar_bo = NULL; 278 279 return VA_STATUS_ERROR_ALLOCATION_FAILED; 280} 281 282 283/* 284 * Reference one IMR buffer from offset 285 * only used to reference a slice IMR buffer which is created outside of video driver 286 */ 287VAStatus psb_buffer_reference_imr(psb_driver_data_p driver_data, 288 uint32_t imr_offset, 289 psb_buffer_p buf 290 ) 291{ 292 VAStatus vaStatus; 293 int ret; 294 295 if (driver_data->rar_bo == NULL) { 296 vaStatus = psb_buffer_init_imr(driver_data); 297 if (vaStatus != VA_STATUS_SUCCESS) { 298 drv_debug_msg(VIDEO_DEBUG_ERROR, "IMR init failed!\n"); 299 return vaStatus; 300 } 301 } 302 303 /* don't need to assign the offset to buffer 304 * so that when destroy the buffer, we just 305 * need to unreference 306 */ 307 /* buf->imr_offset = imr_offset; */ 308 309 /* reference the global IMR BO */ 310 ret = psb_buffer_reference(driver_data, buf, (psb_buffer_p) driver_data->rar_bo); 311 if (ret != VA_STATUS_SUCCESS) { 312 drv_debug_msg(VIDEO_DEBUG_ERROR, "Reference IMR device memory failed\n"); 313 return ret; 314 } 315 316 buf->rar_handle = imr_offset; 317 buf->buffer_ofs = imr_offset; 318 319 /* reference the global IMR buffer, reset buffer type */ 320 buf->type = psb_bt_imr_slice; /* don't need to IMR_release */ 321 322 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Reference IMR buffer, IMR region offset =0x%08x, IMR BO GPU offset hint=0x%08x\n", 323 imr_offset, wsbmBOOffsetHint(buf->drm_buf)); 324 325 return VA_STATUS_SUCCESS; 326} 327