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 (at) intel.com> 26 * Forrest Zhang <forrest.zhang (at) 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 40 #if PSB_MFLD_DUMMY_CODE 41 static VAStatus psb_buffer_offset_camerav4l2(psb_driver_data_p driver_data, 42 psb_buffer_p buf, 43 unsigned int v4l2_buf_offset, 44 unsigned int *bo_offset 45 ) 46 { 47 *bo_offset = v4l2_buf_offset; 48 return VA_STATUS_SUCCESS; 49 } 50 51 52 static VAStatus psb_buffer_offset_cameraci(psb_driver_data_p driver_data, 53 psb_buffer_p buf, 54 unsigned int ci_frame_offset_or_handle, 55 unsigned int *bo_offset 56 ) 57 { 58 *bo_offset = ci_frame_offset_or_handle; 59 60 return VA_STATUS_SUCCESS; 61 } 62 63 64 static int psb_buffer_info_ci(psb_driver_data_p driver_data) 65 { 66 struct drm_lnc_video_getparam_arg arg; 67 unsigned long camera_info[2] = {0, 0}; 68 int ret = 0; 69 70 driver_data->camera_phyaddr = driver_data->camera_size = 0; 71 72 arg.key = LNC_VIDEO_GETPARAM_CI_INFO; 73 arg.value = (uint64_t)((unsigned long) & camera_info[0]); 74 ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, 75 &arg, sizeof(arg)); 76 if (ret == 0) { 77 driver_data->camera_phyaddr = camera_info[0]; 78 driver_data->camera_size = camera_info[1]; 79 drv_debug_msg(VIDEO_DEBUG_GENERAL, "CI region physical address = 0x%08x, size=%dK\n", 80 driver_data->camera_phyaddr, driver_data->camera_size / 1024); 81 82 return ret; 83 } 84 85 drv_debug_msg(VIDEO_DEBUG_GENERAL, "CI region get_info failed\n"); 86 return ret; 87 } 88 89 /* 90 * Allocate global BO which maps camear device memory as encode MMU memory 91 * the global BO shared by several encode surfaces created from camear memory 92 */ 93 static VAStatus psb_buffer_init_camera(psb_driver_data_p driver_data) 94 { 95 int ret = 0; 96 97 /* hasn't grab camera device memory region 98 * grab the whole 4M camera device memory 99 */ 100 driver_data->camera_bo = calloc(1, sizeof(struct psb_buffer_s)); 101 if (driver_data->camera_bo == NULL) 102 return VA_STATUS_ERROR_ALLOCATION_FAILED; 103 104 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Grab whole camera device memory\n"); 105 ret = psb_buffer_create(driver_data, driver_data->camera_size, psb_bt_camera, (psb_buffer_p) driver_data->camera_bo); 106 107 if (ret != VA_STATUS_SUCCESS) { 108 free(driver_data->camera_bo); 109 driver_data->camera_bo = NULL; 110 111 drv_debug_msg(VIDEO_DEBUG_ERROR, "Grab camera device memory failed\n"); 112 } 113 114 return ret; 115 } 116 117 118 /* 119 * Create one buffer from camera device memory 120 * is_v4l2 means if the buffer is V4L2 buffer 121 * id_or_ofs is CI frame ID (actually now is frame offset), or V4L2 buffer offset 122 */ 123 VAStatus psb_buffer_create_camera(psb_driver_data_p driver_data, 124 psb_buffer_p buf, 125 int is_v4l2, 126 int id_or_ofs 127 ) 128 { 129 VAStatus vaStatus; 130 int ret = 0; 131 unsigned int camera_offset = 0; 132 133 if (driver_data->camera_bo == NULL) { 134 if (psb_buffer_info_ci(driver_data)) { 135 drv_debug_msg(VIDEO_DEBUG_ERROR, "Can't get CI region information\n"); 136 return VA_STATUS_ERROR_UNKNOWN; 137 } 138 139 vaStatus = psb_buffer_init_camera(driver_data); 140 if (vaStatus != VA_STATUS_SUCCESS) { 141 drv_debug_msg(VIDEO_DEBUG_ERROR, "Grab camera device memory failed\n"); 142 return ret; 143 } 144 } 145 146 /* reference the global camear BO */ 147 ret = psb_buffer_reference(driver_data, buf, (psb_buffer_p) driver_data->camera_bo); 148 if (ret != VA_STATUS_SUCCESS) { 149 drv_debug_msg(VIDEO_DEBUG_ERROR, "Reference camera device memory failed\n"); 150 return ret; 151 } 152 153 if (is_v4l2) 154 ret = psb_buffer_offset_camerav4l2(driver_data, buf, id_or_ofs, &camera_offset); 155 else 156 ret = psb_buffer_offset_cameraci(driver_data, buf, id_or_ofs, &camera_offset); 157 158 buf->buffer_ofs = camera_offset; 159 160 return ret; 161 } 162 163 /* 164 * Create one buffer from user buffer 165 * id_or_ofs is CI frame ID (actually now is frame offset), or V4L2 buffer offset 166 * user_ptr :virtual address of user buffer start. 167 */ 168 VAStatus psb_buffer_create_camera_from_ub(psb_driver_data_p driver_data, 169 psb_buffer_p buf, 170 int id_or_ofs, 171 int size, 172 const unsigned long * user_ptr) 173 { 174 VAStatus vaStatus = VA_STATUS_SUCCESS; 175 int allignment; 176 uint32_t placement; 177 int ret; 178 179 buf->rar_handle = 0; 180 buf->buffer_ofs = 0; 181 buf->type = psb_bt_user_buffer; 182 buf->user_ptr = (unsigned char *)user_ptr; 183 buf->driver_data = driver_data; 184 185 allignment = 4096; 186 placement = DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_TT | WSBM_PL_FLAG_CACHED | WSBM_PL_FLAG_SHARED ; 187 ret = LOCK_HARDWARE(driver_data); 188 if (ret) { 189 UNLOCK_HARDWARE(driver_data); 190 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 191 DEBUG_FAILURE_RET; 192 return vaStatus; 193 } 194 ret = wsbmGenBuffers(driver_data->main_pool, 1, &buf->drm_buf, 195 allignment, placement); 196 if (!buf->drm_buf) { 197 drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to gen wsbm buffers\n"); 198 UNLOCK_HARDWARE(driver_data); 199 return VA_STATUS_ERROR_ALLOCATION_FAILED; 200 } 201 202 /* here use the placement when gen buffer setted */ 203 ret = wsbmBODataUB(buf->drm_buf, size, NULL, NULL, 0, user_ptr); 204 UNLOCK_HARDWARE(driver_data); 205 if (ret) { 206 drv_debug_msg(VIDEO_DEBUG_ERROR, "failed to alloc wsbm buffers\n"); 207 return VA_STATUS_ERROR_ALLOCATION_FAILED; 208 } 209 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create BO from user buffer 0x%08x (%d byte),BO GPU offset hint=0x%08x\n", 210 user_ptr, size, wsbmBOOffsetHint(buf->drm_buf)); 211 212 213 buf->pl_flags = placement; 214 buf->status = psb_bs_ready; 215 buf->wsbm_synccpu_flag = 0; 216 217 return VA_STATUS_SUCCESS; 218 } 219 #endif 220 221 #ifdef ANDROID 222 #ifndef BAYTRAIL 223 static int psb_buffer_info_rar(psb_driver_data_p driver_data) 224 { 225 struct drm_lnc_video_getparam_arg arg; 226 unsigned long rar_info[2] = {0, 0}; 227 int ret = 0; 228 229 driver_data->rar_phyaddr = driver_data->rar_size = 0; 230 231 arg.key = LNC_VIDEO_GETPARAM_IMR_INFO; 232 arg.value = (uint64_t)((unsigned long) & rar_info[0]); 233 ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, 234 &arg, sizeof(arg)); 235 if (ret == 0) { 236 driver_data->rar_phyaddr = rar_info[0]; 237 driver_data->rar_size = rar_info[1]; 238 driver_data->rar_size = driver_data->rar_size & 0xfffff000; /* page align */ 239 drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR region physical address = 0x%08x, size=%dK\n", 240 driver_data->rar_phyaddr, driver_data->rar_size / 1024); 241 242 return ret; 243 } 244 245 drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR region get size failed\n"); 246 return ret; 247 } 248 #endif 249 #endif 250 251 #ifndef BAYTRAIL 252 static VAStatus psb_buffer_init_imr(psb_driver_data_p driver_data) 253 { 254 int ret = 0; 255 256 /* hasn't grab IMR device memory region 257 * grab the whole IMR3 device memory 258 */ 259 driver_data->rar_bo = calloc(1, sizeof(struct psb_buffer_s)); 260 if (driver_data->rar_bo == NULL) 261 goto exit_error; 262 263 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Init IMR device\n"); 264 #ifdef ANDROID 265 if (psb_buffer_info_rar(driver_data)) { 266 drv_debug_msg(VIDEO_DEBUG_ERROR, "Get IMR region size failed\n"); 267 goto exit_error; 268 } 269 #else 270 drv_debug_msg(VIDEO_DEBUG_ERROR, "NON ANDROID:Get IMR region size failed\n"); 271 goto exit_error; 272 #endif 273 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Grab whole camera device memory\n"); 274 ret = psb_buffer_create(driver_data, driver_data->rar_size, psb_bt_imr, (psb_buffer_p) driver_data->rar_bo); 275 276 if (ret != VA_STATUS_SUCCESS) { 277 drv_debug_msg(VIDEO_DEBUG_ERROR, "Grab IMR device memory failed\n"); 278 goto exit_error; 279 } 280 281 return VA_STATUS_SUCCESS; 282 283 exit_error: 284 if (driver_data->rar_bo) 285 free(driver_data->rar_bo); 286 287 driver_data->rar_bo = NULL; 288 289 return VA_STATUS_ERROR_ALLOCATION_FAILED; 290 } 291 292 293 /* 294 * Reference one IMR buffer from offset 295 * only used to reference a slice IMR buffer which is created outside of video driver 296 */ 297 VAStatus psb_buffer_reference_imr(psb_driver_data_p driver_data, 298 uint32_t imr_offset, 299 psb_buffer_p buf 300 ) 301 { 302 VAStatus vaStatus; 303 int ret; 304 305 if (driver_data->rar_bo == NULL) { 306 vaStatus = psb_buffer_init_imr(driver_data); 307 if (vaStatus != VA_STATUS_SUCCESS) { 308 drv_debug_msg(VIDEO_DEBUG_ERROR, "IMR init failed!\n"); 309 return vaStatus; 310 } 311 } 312 313 /* don't need to assign the offset to buffer 314 * so that when destroy the buffer, we just 315 * need to unreference 316 */ 317 /* buf->imr_offset = imr_offset; */ 318 319 /* reference the global IMR BO */ 320 ret = psb_buffer_reference(driver_data, buf, (psb_buffer_p) driver_data->rar_bo); 321 if (ret != VA_STATUS_SUCCESS) { 322 drv_debug_msg(VIDEO_DEBUG_ERROR, "Reference IMR device memory failed\n"); 323 return ret; 324 } 325 326 buf->rar_handle = imr_offset; 327 buf->buffer_ofs = imr_offset; 328 329 /* reference the global IMR buffer, reset buffer type */ 330 buf->type = psb_bt_imr_slice; /* don't need to IMR_release */ 331 332 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Reference IMR buffer, IMR region offset =0x%08x, IMR BO GPU offset hint=0x%08x\n", 333 imr_offset, wsbmBOOffsetHint(buf->drm_buf)); 334 335 return VA_STATUS_SUCCESS; 336 } 337 #endif 338