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 <wsbm/wsbm_manager.h> 31 32 #include "psb_def.h" 33 #include "psb_surface.h" 34 #include "psb_drv_debug.h" 35 36 /* 37 * Create surface 38 */ 39 VAStatus psb_surface_create(psb_driver_data_p driver_data, 40 int width, int height, int fourcc, unsigned int flags, 41 psb_surface_p psb_surface /* out */ 42 ) 43 { 44 int ret = 0; 45 int buffer_type = psb_bt_surface; 46 47 #ifndef BAYTRAIL 48 if ((flags & IS_ROTATED) || (driver_data->render_mode & VA_RENDER_MODE_LOCAL_OVERLAY)) 49 buffer_type = psb_bt_surface_tt; 50 #endif 51 52 #ifdef PSBVIDEO_MSVDX_DEC_TILING 53 int tiling = GET_SURFACE_INFO_tiling(psb_surface); 54 if (tiling) 55 buffer_type = psb_bt_surface_tiling; 56 #endif 57 58 if (fourcc == VA_FOURCC_NV12) { 59 if ((width <= 0) || (width * height > 5120 * 5120) || (height <= 0)) { 60 return VA_STATUS_ERROR_ALLOCATION_FAILED; 61 } 62 63 if (0) { 64 ; 65 } else if (512 >= width) { 66 psb_surface->stride_mode = STRIDE_512; 67 psb_surface->stride = 512; 68 } else if (1024 >= width) { 69 psb_surface->stride_mode = STRIDE_1024; 70 psb_surface->stride = 1024; 71 } else if (1280 >= width) { 72 psb_surface->stride_mode = STRIDE_1280; 73 psb_surface->stride = 1280; 74 #ifdef PSBVIDEO_MSVDX_DEC_TILING 75 if (tiling) { 76 psb_surface->stride_mode = STRIDE_2048; 77 psb_surface->stride = 2048; 78 } 79 #endif 80 } else if (2048 >= width) { 81 psb_surface->stride_mode = STRIDE_2048; 82 psb_surface->stride = 2048; 83 } else if (4096 >= width) { 84 psb_surface->stride_mode = STRIDE_4096; 85 psb_surface->stride = 4096; 86 } else { 87 psb_surface->stride_mode = STRIDE_NA; 88 psb_surface->stride = (width + 0x3f) & ~0x3f; 89 } 90 91 psb_surface->luma_offset = 0; 92 psb_surface->chroma_offset = psb_surface->stride * height; 93 psb_surface->size = (psb_surface->stride * height * 3) / 2; 94 psb_surface->extra_info[4] = VA_FOURCC_NV12; 95 } else if (fourcc == VA_FOURCC_RGBA) { 96 unsigned int pitchAlignMask = 63; 97 psb_surface->stride_mode = STRIDE_NA; 98 psb_surface->stride = (width * 4 + pitchAlignMask) & ~pitchAlignMask;; 99 psb_surface->luma_offset = 0; 100 psb_surface->chroma_offset = 0; 101 psb_surface->size = psb_surface->stride * height; 102 psb_surface->extra_info[4] = VA_FOURCC_RGBA; 103 } else if (fourcc == VA_FOURCC_YV16) { 104 if ((width <= 0) || (width * height > 5120 * 5120) || (height <= 0)) { 105 return VA_STATUS_ERROR_ALLOCATION_FAILED; 106 } 107 108 if (0) { 109 ; 110 } else if (512 >= width) { 111 psb_surface->stride_mode = STRIDE_512; 112 psb_surface->stride = 512; 113 } else if (1024 >= width) { 114 psb_surface->stride_mode = STRIDE_1024; 115 psb_surface->stride = 1024; 116 } else if (1280 >= width) { 117 psb_surface->stride_mode = STRIDE_1280; 118 psb_surface->stride = 1280; 119 #ifdef PSBVIDEO_MSVDX_DEC_TILING 120 if (tiling) { 121 psb_surface->stride_mode = STRIDE_2048; 122 psb_surface->stride = 2048; 123 } 124 #endif 125 } else if (2048 >= width) { 126 psb_surface->stride_mode = STRIDE_2048; 127 psb_surface->stride = 2048; 128 } else if (4096 >= width) { 129 psb_surface->stride_mode = STRIDE_4096; 130 psb_surface->stride = 4096; 131 } else { 132 psb_surface->stride_mode = STRIDE_NA; 133 psb_surface->stride = (width + 0x3f) & ~0x3f; 134 } 135 136 psb_surface->luma_offset = 0; 137 psb_surface->chroma_offset = psb_surface->stride * height; 138 psb_surface->size = psb_surface->stride * height * 2; 139 psb_surface->extra_info[4] = VA_FOURCC_YV16; 140 } else if (fourcc == VA_FOURCC_YV32) { 141 psb_surface->stride_mode = STRIDE_NA; 142 psb_surface->stride = (width + 0x3f) & ~0x3f; /*round up to 16 */ 143 psb_surface->luma_offset = 0; 144 psb_surface->chroma_offset = psb_surface->stride * height; 145 psb_surface->size = psb_surface->stride * height * 4; 146 psb_surface->extra_info[4] = VA_FOURCC_YV32; 147 } 148 149 if (flags & IS_PROTECTED) 150 SET_SURFACE_INFO_protect(psb_surface, 1); 151 152 ret = psb_buffer_create(driver_data, psb_surface->size, buffer_type, &psb_surface->buf); 153 154 return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS; 155 } 156 157 158 159 VAStatus psb_surface_create_for_userptr( 160 psb_driver_data_p driver_data, 161 int width, int height, 162 unsigned size, /* total buffer size need to be allocated */ 163 unsigned int __maybe_unused fourcc, /* expected fourcc */ 164 unsigned int luma_stride, /* luma stride, could be width aligned with a special value */ 165 unsigned int __maybe_unused chroma_u_stride, /* chroma stride */ 166 unsigned int __maybe_unused chroma_v_stride, 167 unsigned int luma_offset, /* could be 0 */ 168 unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */ 169 unsigned int __maybe_unused chroma_v_offset, 170 psb_surface_p psb_surface /* out */ 171 ) 172 { 173 int ret; 174 175 if ((width <= 0) || (width > 5120) || (height <= 0) || (height > 5120)) 176 return VA_STATUS_ERROR_ALLOCATION_FAILED; 177 178 psb_surface->stride_mode = STRIDE_NA; 179 psb_surface->stride = luma_stride; 180 181 182 psb_surface->luma_offset = luma_offset; 183 psb_surface->chroma_offset = chroma_u_offset; 184 psb_surface->size = size; 185 psb_surface->extra_info[4] = VA_FOURCC_NV12; 186 187 ret = psb_buffer_create(driver_data, psb_surface->size, psb_bt_cpu_vpu_shared, &psb_surface->buf); 188 189 return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS; 190 } 191 192 VAStatus psb_surface_create_from_kbuf( 193 psb_driver_data_p driver_data, 194 int width, int height, 195 unsigned size, /* total buffer size need to be allocated */ 196 unsigned int __maybe_unused fourcc, /* expected fourcc */ 197 int __maybe_unused kbuf_handle, 198 unsigned int luma_stride, /* luma stride, could be width aligned with a special value */ 199 unsigned int __maybe_unused chroma_u_stride, /* chroma stride */ 200 unsigned int __maybe_unused chroma_v_stride, 201 unsigned int __maybe_unused luma_offset, /* could be 0 */ 202 unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */ 203 unsigned int __maybe_unused chroma_v_offset, 204 psb_surface_p psb_surface /* out */ 205 ) 206 { 207 int ret; 208 209 if ((width <= 0) || (width > 5120) || (height <= 0) || (height > 5120)) 210 return VA_STATUS_ERROR_ALLOCATION_FAILED; 211 212 psb_surface->stride = luma_stride; 213 214 if (0) { 215 ; 216 } else if (512 == luma_stride) { 217 psb_surface->stride_mode = STRIDE_512; 218 } else if (1024 == luma_stride) { 219 psb_surface->stride_mode = STRIDE_1024; 220 } else if (1280 == luma_stride) { 221 psb_surface->stride_mode = STRIDE_1280; 222 } else if (2048 == luma_stride) { 223 psb_surface->stride_mode = STRIDE_2048; 224 } else if (4096 == luma_stride) { 225 psb_surface->stride_mode = STRIDE_4096; 226 } else { 227 psb_surface->stride_mode = STRIDE_NA; 228 } 229 230 psb_surface->luma_offset = luma_offset; 231 psb_surface->chroma_offset = chroma_u_offset; 232 psb_surface->size = size; 233 psb_surface->extra_info[4] = VA_FOURCC_NV12; 234 235 ret = psb_kbuffer_reference(driver_data, &psb_surface->buf, kbuf_handle); 236 237 return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS; 238 } 239 240 #if PSB_MFLD_DUMMY_CODE 241 /* id_or_ofs: it is frame ID or frame offset in camear device memory 242 * for CI frame: it it always frame offset currently 243 * for v4l2 buf: it is offset used in V4L2 buffer mmap 244 */ 245 VAStatus psb_surface_create_camera(psb_driver_data_p driver_data, 246 int width, int height, int stride, int size, 247 psb_surface_p psb_surface, /* out */ 248 int is_v4l2, 249 unsigned int id_or_ofs 250 ) 251 { 252 int ret; 253 254 if ((width <= 0) || (width > 4096) || (height <= 0) || (height > 4096)) { 255 return VA_STATUS_ERROR_ALLOCATION_FAILED; 256 } 257 258 psb_surface->stride = stride; 259 if ((width == 640) && (height == 360)) { 260 drv_debug_msg(VIDEO_DEBUG_GENERAL, "CI Frame is 640x360, and allocated as 640x368,adjust chroma_offset\n"); 261 psb_surface->chroma_offset = psb_surface->stride * 368; 262 } else 263 psb_surface->chroma_offset = psb_surface->stride * height; 264 psb_surface->size = (psb_surface->stride * height * 3) / 2; 265 266 ret = psb_buffer_create_camera(driver_data, &psb_surface->buf, 267 is_v4l2, id_or_ofs); 268 269 if (ret != VA_STATUS_SUCCESS) { 270 psb_surface_destroy(psb_surface); 271 272 drv_debug_msg(VIDEO_DEBUG_ERROR, "Get surfae offset of camear device memory failed!\n"); 273 return ret; 274 } 275 276 return VA_STATUS_SUCCESS; 277 } 278 279 /* id_or_ofs: it is frame ID or frame offset in camear device memory 280 * for CI frame: it it always frame offset currently 281 * for v4l2 buf: it is offset used in V4L2 buffer mmap 282 * user_ptr: virtual address of user buffer. 283 */ 284 VAStatus psb_surface_create_camera_from_ub(psb_driver_data_p driver_data, 285 int width, int height, int stride, int size, 286 psb_surface_p psb_surface, /* out */ 287 int is_v4l2, 288 unsigned int id_or_ofs, 289 const unsigned long *user_ptr) 290 { 291 int ret; 292 293 if ((width <= 0) || (width > 4096) || (height <= 0) || (height > 4096)) { 294 return VA_STATUS_ERROR_ALLOCATION_FAILED; 295 } 296 297 psb_surface->stride = stride; 298 psb_surface->chroma_offset = psb_surface->stride * height; 299 psb_surface->size = (psb_surface->stride * height * 3) / 2; 300 301 ret = psb_buffer_create_camera_from_ub(driver_data, &psb_surface->buf, 302 is_v4l2, psb_surface->size, user_ptr); 303 304 if (ret != VA_STATUS_SUCCESS) { 305 psb_surface_destroy(psb_surface); 306 307 drv_debug_msg(VIDEO_DEBUG_ERROR, "Get surfae offset of camear device memory failed!\n"); 308 return ret; 309 } 310 311 return VA_STATUS_SUCCESS; 312 } 313 #endif 314 315 /* 316 * Temporarily map surface and set all chroma values of surface to 'chroma' 317 */ 318 VAStatus psb_surface_set_chroma(psb_surface_p psb_surface, int chroma) 319 { 320 unsigned char *surface_data; 321 int ret = psb_buffer_map(&psb_surface->buf, &surface_data); 322 323 if (ret) return VA_STATUS_ERROR_UNKNOWN; 324 325 memset(surface_data + psb_surface->chroma_offset, chroma, psb_surface->size - psb_surface->chroma_offset); 326 327 psb_buffer_unmap(&psb_surface->buf); 328 329 return VA_STATUS_SUCCESS; 330 } 331 332 /* 333 * Destroy surface 334 */ 335 void psb_surface_destroy(psb_surface_p psb_surface) 336 { 337 psb_buffer_destroy(&psb_surface->buf); 338 if (NULL != psb_surface->in_loop_buf) 339 psb_buffer_destroy(psb_surface->in_loop_buf); 340 341 } 342 343 VAStatus psb_surface_sync(psb_surface_p psb_surface) 344 { 345 wsbmBOWaitIdle(psb_surface->buf.drm_buf, 0); 346 347 return VA_STATUS_SUCCESS; 348 } 349 350 VAStatus psb_surface_query_status(psb_surface_p psb_surface, VASurfaceStatus *status) 351 { 352 int ret; 353 uint32_t synccpu_flag = WSBM_SYNCCPU_READ | WSBM_SYNCCPU_WRITE | WSBM_SYNCCPU_DONT_BLOCK; 354 355 ret = wsbmBOSyncForCpu(psb_surface->buf.drm_buf, synccpu_flag); 356 357 if (ret == 0) { 358 (void) wsbmBOReleaseFromCpu(psb_surface->buf.drm_buf, synccpu_flag); 359 *status = VASurfaceReady; 360 } else { 361 *status = VASurfaceRendering; 362 } 363 return VA_STATUS_SUCCESS; 364 } 365 366 /* 367 * Set current displaying surface info to kernel 368 * so that other component can access it in another process 369 */ 370 int psb_surface_set_displaying(psb_driver_data_p driver_data, 371 int width, int height, 372 psb_surface_p psb_surface) 373 { 374 struct drm_lnc_video_getparam_arg arg; 375 struct drm_video_displaying_frameinfo value; 376 int ret = 0; 377 378 if (psb_surface) { 379 value.buf_handle = (uint32_t)(wsbmKBufHandle(wsbmKBuf(psb_surface->buf.drm_buf))); 380 value.width = width; 381 value.height = height; 382 value.size = psb_surface->size; 383 value.format = psb_surface->extra_info[4]; 384 value.luma_stride = psb_surface->stride; 385 value.chroma_u_stride = psb_surface->stride; 386 value.chroma_v_stride = psb_surface->stride; 387 value.luma_offset = psb_surface->luma_offset; 388 value.chroma_u_offset = psb_surface->chroma_offset; 389 value.chroma_v_offset = psb_surface->chroma_offset; 390 } else /* clean kernel displaying surface info */ 391 memset(&value, 0, sizeof(value)); 392 393 arg.key = IMG_VIDEO_SET_DISPLAYING_FRAME; 394 arg.value = (uint64_t)((unsigned long) & value); 395 ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset, 396 &arg, sizeof(arg)); 397 if (ret != 0) 398 drv_debug_msg(VIDEO_DEBUG_ERROR, "IMG_VIDEO_SET_DISPLAYING_FRAME failed\n"); 399 400 return ret; 401 } 402