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 
40 #if PSB_MFLD_DUMMY_CODE
psb_buffer_offset_camerav4l2(psb_driver_data_p driver_data,psb_buffer_p buf,unsigned int v4l2_buf_offset,unsigned int * bo_offset)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 
psb_buffer_offset_cameraci(psb_driver_data_p driver_data,psb_buffer_p buf,unsigned int ci_frame_offset_or_handle,unsigned int * bo_offset)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 
psb_buffer_info_ci(psb_driver_data_p driver_data)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  */
psb_buffer_init_camera(psb_driver_data_p driver_data)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  */
psb_buffer_create_camera(psb_driver_data_p driver_data,psb_buffer_p buf,int is_v4l2,int id_or_ofs)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  */
psb_buffer_create_camera_from_ub(psb_driver_data_p driver_data,psb_buffer_p buf,int id_or_ofs,int size,const unsigned long * user_ptr)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
psb_buffer_info_rar(psb_driver_data_p driver_data)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
psb_buffer_init_imr(psb_driver_data_p driver_data)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  */
psb_buffer_reference_imr(psb_driver_data_p driver_data,uint32_t imr_offset,psb_buffer_p buf)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