psb_buffer_dm.c revision 61e067e1c2cfca5234c4a7fa2af351206b543904
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
41static 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
52static 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
64static 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 */
93static 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 */
123VAStatus 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 */
168VAStatus 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
221static int psb_buffer_info_rar(psb_driver_data_p driver_data)
222{
223    struct drm_lnc_video_getparam_arg arg;
224    unsigned long rar_info[2] = {0, 0};
225    int ret = 0;
226
227    driver_data->rar_phyaddr = driver_data->rar_size = 0;
228
229    arg.key = LNC_VIDEO_GETPARAM_IMR_INFO;
230    arg.value = (uint64_t)((unsigned long) & rar_info[0]);
231    ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
232                              &arg, sizeof(arg));
233    if (ret == 0) {
234        driver_data->rar_phyaddr = rar_info[0];
235        driver_data->rar_size = rar_info[1];
236        driver_data->rar_size = driver_data->rar_size & 0xfffff000; /* page align */
237        drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR region physical address = 0x%08x, size=%dK\n",
238                                 driver_data->rar_phyaddr,  driver_data->rar_size / 1024);
239
240        return ret;
241    }
242
243    drv_debug_msg(VIDEO_DEBUG_GENERAL, "RAR region get size failed\n");
244    return ret;
245}
246
247
248static VAStatus psb_buffer_init_imr(psb_driver_data_p driver_data)
249{
250    int ret = 0;
251
252    /* hasn't grab IMR device memory region
253     * grab the whole IMR3 device memory
254     */
255    driver_data->rar_bo = calloc(1, sizeof(struct psb_buffer_s));
256    if (driver_data->rar_bo == NULL)
257        goto exit_error;
258
259    drv_debug_msg(VIDEO_DEBUG_GENERAL, "Init IMR device\n");
260    if (psb_buffer_info_rar(driver_data)) {
261        drv_debug_msg(VIDEO_DEBUG_ERROR, "Get IMR region size failed\n");
262        goto exit_error;
263    }
264
265    drv_debug_msg(VIDEO_DEBUG_GENERAL, "Grab whole camera device memory\n");
266    ret = psb_buffer_create(driver_data, driver_data->rar_size, psb_bt_imr, (psb_buffer_p) driver_data->rar_bo);
267
268    if (ret != VA_STATUS_SUCCESS) {
269        drv_debug_msg(VIDEO_DEBUG_ERROR, "Grab IMR device memory failed\n");
270        goto exit_error;
271    }
272
273    return VA_STATUS_SUCCESS;
274
275exit_error:
276    if (driver_data->rar_bo)
277        free(driver_data->rar_bo);
278
279    driver_data->rar_bo = NULL;
280
281    return VA_STATUS_ERROR_ALLOCATION_FAILED;
282}
283
284
285/*
286 * Reference one IMR buffer from offset
287 * only used to reference a slice IMR buffer which is created outside of video driver
288 */
289VAStatus psb_buffer_reference_imr(psb_driver_data_p driver_data,
290                                  uint32_t imr_offset,
291                                  psb_buffer_p buf
292                                 )
293{
294    VAStatus vaStatus;
295    int ret;
296
297    if (driver_data->rar_bo  == NULL) {
298        vaStatus = psb_buffer_init_imr(driver_data);
299        if (vaStatus != VA_STATUS_SUCCESS) {
300            drv_debug_msg(VIDEO_DEBUG_ERROR, "IMR init failed!\n");
301            return vaStatus;
302        }
303    }
304
305    /* don't need to assign the offset to buffer
306     * so that when destroy the buffer, we just
307     * need to unreference
308     */
309    /* buf->imr_offset = imr_offset; */
310
311    /* reference the global IMR BO */
312    ret = psb_buffer_reference(driver_data, buf, (psb_buffer_p) driver_data->rar_bo);
313    if (ret != VA_STATUS_SUCCESS) {
314        drv_debug_msg(VIDEO_DEBUG_ERROR, "Reference IMR device memory failed\n");
315        return ret;
316    }
317
318    buf->rar_handle = imr_offset;
319    buf->buffer_ofs = imr_offset;
320
321    /* reference the global IMR buffer, reset buffer type */
322    buf->type = psb_bt_imr_slice; /* don't need to IMR_release */
323
324    drv_debug_msg(VIDEO_DEBUG_GENERAL, "Reference IMR buffer, IMR region offset =0x%08x, IMR BO GPU offset hint=0x%08x\n",
325                             imr_offset, wsbmBOOffsetHint(buf->drm_buf));
326
327    return VA_STATUS_SUCCESS;
328}
329