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