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 <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 */
psb_surface_create(psb_driver_data_p driver_data,int width,int height,int fourcc,unsigned int flags,psb_surface_p psb_surface)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
psb_surface_create_for_userptr(psb_driver_data_p driver_data,int width,int height,unsigned size,unsigned int __maybe_unused fourcc,unsigned int luma_stride,unsigned int __maybe_unused chroma_u_stride,unsigned int __maybe_unused chroma_v_stride,unsigned int luma_offset,unsigned int chroma_u_offset,unsigned int __maybe_unused chroma_v_offset,psb_surface_p psb_surface)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 psb_surface->extra_info[8] = VA_FOURCC_NV12;
187
188 ret = psb_buffer_create(driver_data, psb_surface->size, psb_bt_cpu_vpu_shared, &psb_surface->buf);
189
190 return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS;
191 }
192
psb_surface_create_from_kbuf(psb_driver_data_p driver_data,int width,int height,unsigned size,unsigned int __maybe_unused fourcc,int __maybe_unused kbuf_handle,unsigned int luma_stride,unsigned int __maybe_unused chroma_u_stride,unsigned int __maybe_unused chroma_v_stride,unsigned int __maybe_unused luma_offset,unsigned int chroma_u_offset,unsigned int __maybe_unused chroma_v_offset,psb_surface_p psb_surface)193 VAStatus psb_surface_create_from_kbuf(
194 psb_driver_data_p driver_data,
195 int width, int height,
196 unsigned size, /* total buffer size need to be allocated */
197 unsigned int __maybe_unused fourcc, /* expected fourcc */
198 int __maybe_unused kbuf_handle,
199 unsigned int luma_stride, /* luma stride, could be width aligned with a special value */
200 unsigned int __maybe_unused chroma_u_stride, /* chroma stride */
201 unsigned int __maybe_unused chroma_v_stride,
202 unsigned int __maybe_unused luma_offset, /* could be 0 */
203 unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */
204 unsigned int __maybe_unused chroma_v_offset,
205 psb_surface_p psb_surface /* out */
206 )
207 {
208 int ret;
209
210 if ((width <= 0) || (width > 5120) || (height <= 0) || (height > 5120))
211 return VA_STATUS_ERROR_ALLOCATION_FAILED;
212
213 psb_surface->stride = luma_stride;
214
215 if (0) {
216 ;
217 } else if (512 == luma_stride) {
218 psb_surface->stride_mode = STRIDE_512;
219 } else if (1024 == luma_stride) {
220 psb_surface->stride_mode = STRIDE_1024;
221 } else if (1280 == luma_stride) {
222 psb_surface->stride_mode = STRIDE_1280;
223 } else if (2048 == luma_stride) {
224 psb_surface->stride_mode = STRIDE_2048;
225 } else if (4096 == luma_stride) {
226 psb_surface->stride_mode = STRIDE_4096;
227 } else {
228 psb_surface->stride_mode = STRIDE_NA;
229 }
230
231 psb_surface->luma_offset = luma_offset;
232 psb_surface->chroma_offset = chroma_u_offset;
233 psb_surface->size = size;
234 psb_surface->extra_info[4] = VA_FOURCC_NV12;
235 psb_surface->extra_info[8] = VA_FOURCC_NV12;
236
237 ret = psb_kbuffer_reference(driver_data, &psb_surface->buf, kbuf_handle);
238
239 return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS;
240 }
241
242 #if PSB_MFLD_DUMMY_CODE
243 /* id_or_ofs: it is frame ID or frame offset in camear device memory
244 * for CI frame: it it always frame offset currently
245 * for v4l2 buf: it is offset used in V4L2 buffer mmap
246 */
psb_surface_create_camera(psb_driver_data_p driver_data,int width,int height,int stride,int size,psb_surface_p psb_surface,int is_v4l2,unsigned int id_or_ofs)247 VAStatus psb_surface_create_camera(psb_driver_data_p driver_data,
248 int width, int height, int stride, int size,
249 psb_surface_p psb_surface, /* out */
250 int is_v4l2,
251 unsigned int id_or_ofs
252 )
253 {
254 int ret;
255
256 if ((width <= 0) || (width > 4096) || (height <= 0) || (height > 4096)) {
257 return VA_STATUS_ERROR_ALLOCATION_FAILED;
258 }
259
260 psb_surface->stride = stride;
261 if ((width == 640) && (height == 360)) {
262 drv_debug_msg(VIDEO_DEBUG_GENERAL, "CI Frame is 640x360, and allocated as 640x368,adjust chroma_offset\n");
263 psb_surface->chroma_offset = psb_surface->stride * 368;
264 } else
265 psb_surface->chroma_offset = psb_surface->stride * height;
266 psb_surface->size = (psb_surface->stride * height * 3) / 2;
267
268 ret = psb_buffer_create_camera(driver_data, &psb_surface->buf,
269 is_v4l2, id_or_ofs);
270
271 if (ret != VA_STATUS_SUCCESS) {
272 psb_surface_destroy(psb_surface);
273
274 drv_debug_msg(VIDEO_DEBUG_ERROR, "Get surfae offset of camear device memory failed!\n");
275 return ret;
276 }
277
278 return VA_STATUS_SUCCESS;
279 }
280
281 /* id_or_ofs: it is frame ID or frame offset in camear device memory
282 * for CI frame: it it always frame offset currently
283 * for v4l2 buf: it is offset used in V4L2 buffer mmap
284 * user_ptr: virtual address of user buffer.
285 */
psb_surface_create_camera_from_ub(psb_driver_data_p driver_data,int width,int height,int stride,int size,psb_surface_p psb_surface,int is_v4l2,unsigned int id_or_ofs,const unsigned long * user_ptr)286 VAStatus psb_surface_create_camera_from_ub(psb_driver_data_p driver_data,
287 int width, int height, int stride, int size,
288 psb_surface_p psb_surface, /* out */
289 int is_v4l2,
290 unsigned int id_or_ofs,
291 const unsigned long *user_ptr)
292 {
293 int ret;
294
295 if ((width <= 0) || (width > 4096) || (height <= 0) || (height > 4096)) {
296 return VA_STATUS_ERROR_ALLOCATION_FAILED;
297 }
298
299 psb_surface->stride = stride;
300 psb_surface->chroma_offset = psb_surface->stride * height;
301 psb_surface->size = (psb_surface->stride * height * 3) / 2;
302
303 ret = psb_buffer_create_camera_from_ub(driver_data, &psb_surface->buf,
304 is_v4l2, psb_surface->size, user_ptr);
305
306 if (ret != VA_STATUS_SUCCESS) {
307 psb_surface_destroy(psb_surface);
308
309 drv_debug_msg(VIDEO_DEBUG_ERROR, "Get surfae offset of camear device memory failed!\n");
310 return ret;
311 }
312
313 return VA_STATUS_SUCCESS;
314 }
315 #endif
316
317 /*
318 * Temporarily map surface and set all chroma values of surface to 'chroma'
319 */
psb_surface_set_chroma(psb_surface_p psb_surface,int chroma)320 VAStatus psb_surface_set_chroma(psb_surface_p psb_surface, int chroma)
321 {
322 unsigned char *surface_data;
323 int ret = psb_buffer_map(&psb_surface->buf, &surface_data);
324
325 if (ret) return VA_STATUS_ERROR_UNKNOWN;
326
327 memset(surface_data + psb_surface->chroma_offset, chroma, psb_surface->size - psb_surface->chroma_offset);
328
329 psb_buffer_unmap(&psb_surface->buf);
330
331 return VA_STATUS_SUCCESS;
332 }
333
334 /*
335 * Destroy surface
336 */
psb_surface_destroy(psb_surface_p psb_surface)337 void psb_surface_destroy(psb_surface_p psb_surface)
338 {
339 psb_buffer_destroy(&psb_surface->buf);
340 if (NULL != psb_surface->in_loop_buf)
341 psb_buffer_destroy(psb_surface->in_loop_buf);
342
343 }
344
psb_surface_sync(psb_surface_p psb_surface)345 VAStatus psb_surface_sync(psb_surface_p psb_surface)
346 {
347 wsbmBOWaitIdle(psb_surface->buf.drm_buf, 0);
348
349 return VA_STATUS_SUCCESS;
350 }
351
psb_surface_query_status(psb_surface_p psb_surface,VASurfaceStatus * status)352 VAStatus psb_surface_query_status(psb_surface_p psb_surface, VASurfaceStatus *status)
353 {
354 int ret;
355 uint32_t synccpu_flag = WSBM_SYNCCPU_READ | WSBM_SYNCCPU_WRITE | WSBM_SYNCCPU_DONT_BLOCK;
356
357 ret = wsbmBOSyncForCpu(psb_surface->buf.drm_buf, synccpu_flag);
358
359 if (ret == 0) {
360 (void) wsbmBOReleaseFromCpu(psb_surface->buf.drm_buf, synccpu_flag);
361 *status = VASurfaceReady;
362 } else {
363 *status = VASurfaceRendering;
364 }
365 return VA_STATUS_SUCCESS;
366 }
367
368 /*
369 * Set current displaying surface info to kernel
370 * so that other component can access it in another process
371 */
psb_surface_set_displaying(psb_driver_data_p driver_data,int width,int height,psb_surface_p psb_surface)372 int psb_surface_set_displaying(psb_driver_data_p driver_data,
373 int width, int height,
374 psb_surface_p psb_surface)
375 {
376 struct drm_lnc_video_getparam_arg arg;
377 struct drm_video_displaying_frameinfo value;
378 int ret = 0;
379
380 if (psb_surface) {
381 value.buf_handle = (uint32_t)(wsbmKBufHandle(wsbmKBuf(psb_surface->buf.drm_buf)));
382 value.width = width;
383 value.height = height;
384 value.size = psb_surface->size;
385 value.format = psb_surface->extra_info[4];
386 value.luma_stride = psb_surface->stride;
387 value.chroma_u_stride = psb_surface->stride;
388 value.chroma_v_stride = psb_surface->stride;
389 value.luma_offset = psb_surface->luma_offset;
390 value.chroma_u_offset = psb_surface->chroma_offset;
391 value.chroma_v_offset = psb_surface->chroma_offset;
392 } else /* clean kernel displaying surface info */
393 memset(&value, 0, sizeof(value));
394
395 arg.key = IMG_VIDEO_SET_DISPLAYING_FRAME;
396 arg.value = (uint64_t)((unsigned long) & value);
397 ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
398 &arg, sizeof(arg));
399 if (ret != 0)
400 drv_debug_msg(VIDEO_DEBUG_ERROR, "IMG_VIDEO_SET_DISPLAYING_FRAME failed\n");
401
402 return ret;
403 }
404