psb_buffer_dm.c revision dc1209519284865899ca8d990b3a2c7dbca8ae08
1/*
2 * INTEL CONFIDENTIAL
3 * Copyright 2007 Intel Corporation. All Rights Reserved.
4 *
5 * The source code contained or described herein and all documents related to
6 * the source code ("Material") are owned by Intel Corporation or its suppliers
7 * or licensors. Title to the Material remains with Intel Corporation or its
8 * suppliers and licensors. The Material may contain trade secrets and
9 * proprietary and confidential information of Intel Corporation and its
10 * suppliers and licensors, and is protected by worldwide copyright and trade
11 * secret laws and treaty provisions. No part of the Material may be used,
12 * copied, reproduced, modified, published, uploaded, posted, transmitted,
13 * distributed, or disclosed in any way without Intel's prior express written
14 * permission.
15 *
16 * No license under any patent, copyright, trade secret or other intellectual
17 * property right is granted to or conferred upon you by disclosure or delivery
18 * of the Materials, either expressly, by implication, inducement, estoppel or
19 * otherwise. Any license under such intellectual property rights must be
20 * express and approved by Intel in writing.
21 */
22
23#include "psb_buffer.h"
24
25#include <errno.h>
26#include <stdlib.h>
27#include <unistd.h>
28#include <wsbm/wsbm_manager.h>
29/* #include <linux/rar_register.h> */
30
31#include "psb_drm.h"
32#include "psb_def.h"
33
34
35static VAStatus psb_buffer_offset_camerav4l2(psb_driver_data_p driver_data,
36        psb_buffer_p buf,
37        unsigned int v4l2_buf_offset,
38        unsigned int *bo_offset
39                                            )
40{
41    *bo_offset = v4l2_buf_offset;
42    return VA_STATUS_SUCCESS;
43}
44
45
46static VAStatus psb_buffer_offset_cameraci(psb_driver_data_p driver_data,
47        psb_buffer_p buf,
48        unsigned int ci_frame_offset_or_handle,
49        unsigned int *bo_offset
50                                          )
51{
52    *bo_offset = ci_frame_offset_or_handle;
53
54    return VA_STATUS_SUCCESS;
55}
56
57
58static int psb_buffer_info_ci(psb_driver_data_p driver_data)
59{
60    struct drm_lnc_video_getparam_arg arg;
61    unsigned long camera_info[2] = {0, 0};
62    int ret = 0;
63
64    driver_data->camera_phyaddr = driver_data->camera_size = 0;
65
66    arg.key = LNC_VIDEO_GETPARAM_CI_INFO;
67    arg.value = (uint64_t)((unsigned long) & camera_info[0]);
68    ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
69                              &arg, sizeof(arg));
70    if (ret == 0) {
71        driver_data->camera_phyaddr = camera_info[0];
72        driver_data->camera_size = camera_info[1];
73        psb__information_message("CI region physical address = 0x%08x, size=%dK\n",
74                                 driver_data->camera_phyaddr,  driver_data->camera_size / 1024);
75
76        return ret;
77    }
78
79    psb__information_message("CI region get_info failed\n");
80    return ret;
81}
82
83/*
84 * Allocate global BO which maps camear device memory as encode MMU memory
85 * the global BO shared by several encode surfaces created from camear memory
86 */
87static VAStatus psb_buffer_init_camera(psb_driver_data_p driver_data)
88{
89    int ret = 0;
90
91    /* hasn't grab camera device memory region
92     * grab the whole 4M camera device memory
93     */
94    driver_data->camera_bo = calloc(1, sizeof(struct psb_buffer_s));
95    if (driver_data->camera_bo == NULL)
96        return VA_STATUS_ERROR_ALLOCATION_FAILED;
97
98    psb__information_message("Grab whole camera device memory\n");
99    ret = psb_buffer_create(driver_data, driver_data->camera_size, psb_bt_camera, (psb_buffer_p) driver_data->camera_bo);
100
101    if (ret != VA_STATUS_SUCCESS) {
102        free(driver_data->camera_bo);
103        driver_data->camera_bo = NULL;
104
105        psb__error_message("Grab camera device memory failed\n");
106    }
107
108    return ret;
109}
110
111
112/*
113 * Create one buffer from camera device memory
114 * is_v4l2 means if the buffer is V4L2 buffer
115 * id_or_ofs is CI frame ID (actually now is frame offset), or V4L2 buffer offset
116 */
117VAStatus psb_buffer_create_camera(psb_driver_data_p driver_data,
118                                  psb_buffer_p buf,
119                                  int is_v4l2,
120                                  int id_or_ofs
121                                 )
122{
123    VAStatus vaStatus;
124    int ret = 0;
125    unsigned int camera_offset = 0;
126
127    if (driver_data->camera_bo  == NULL) {
128        if (psb_buffer_info_ci(driver_data)) {
129            psb__error_message("Can't get CI region information\n");
130            return VA_STATUS_ERROR_UNKNOWN;
131        }
132
133        vaStatus = psb_buffer_init_camera(driver_data);
134        if (vaStatus != VA_STATUS_SUCCESS) {
135            psb__error_message("Grab camera device memory failed\n");
136            return ret;
137        }
138    }
139
140    /* reference the global camear BO */
141    ret = psb_buffer_reference(driver_data, buf, (psb_buffer_p) driver_data->camera_bo);
142    if (ret != VA_STATUS_SUCCESS) {
143        psb__error_message("Reference camera device memory failed\n");
144        return ret;
145    }
146
147    if (is_v4l2)
148        ret = psb_buffer_offset_camerav4l2(driver_data, buf, id_or_ofs, &camera_offset);
149    else
150        ret = psb_buffer_offset_cameraci(driver_data, buf, id_or_ofs, &camera_offset);
151
152    buf->buffer_ofs = camera_offset;
153
154    return ret;
155}
156
157/*
158 * Create one buffer from user buffer
159 * id_or_ofs is CI frame ID (actually now is frame offset), or V4L2 buffer offset
160 * user_ptr :virtual address of user buffer start.
161 */
162VAStatus psb_buffer_create_camera_from_ub(psb_driver_data_p driver_data,
163        psb_buffer_p buf,
164        int id_or_ofs,
165        int size,
166        const unsigned long * user_ptr)
167{
168    VAStatus vaStatus = VA_STATUS_SUCCESS;
169    int allignment;
170    uint32_t placement;
171    int ret;
172
173    buf->rar_handle = 0;
174    buf->buffer_ofs = 0;
175    buf->type = psb_bt_user_buffer;
176    buf->user_ptr = (void *)user_ptr;
177    buf->driver_data = driver_data;
178
179    allignment = 4096;
180    placement =  DRM_PSB_FLAG_MEM_MMU | WSBM_PL_FLAG_TT | WSBM_PL_FLAG_CACHED | WSBM_PL_FLAG_SHARED ;
181    ret = LOCK_HARDWARE(driver_data);
182    if (ret) {
183        UNLOCK_HARDWARE(driver_data);
184        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
185        DEBUG_FAILURE_RET;
186        return vaStatus;
187    }
188    ret = wsbmGenBuffers(driver_data->main_pool, 1, &buf->drm_buf,
189                         allignment, placement);
190    if (!buf->drm_buf) {
191        psb__error_message("failed to gen wsbm buffers\n");
192        UNLOCK_HARDWARE(driver_data);
193        return VA_STATUS_ERROR_ALLOCATION_FAILED;
194    }
195
196#ifndef ANDROID
197    extern int wsbmBODataUB(struct _WsbmBufferObject *buf,
198                                unsigned size, const void *data,
199                                struct _WsbmBufferPool *newPool, uint32_t placement, const unsigned long *user_ptr);
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        psb__error_message("failed to alloc wsbm buffers\n");
206        return VA_STATUS_ERROR_ALLOCATION_FAILED;
207    }
208    psb__information_message("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#endif
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
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_RAR_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        psb__information_message("RAR region physical address = 0x%08x, size=%dK\n",
237                                 driver_data->rar_phyaddr,  driver_data->rar_size / 1024);
238
239        return ret;
240    }
241
242    psb__information_message("RAR region get size failed\n");
243    return ret;
244}
245
246
247static int psb_buffer_offset_rar(psb_driver_data_p driver_data,
248                                 psb_buffer_p buf,
249                                 uint32_t rar_handle,
250                                 unsigned int *bo_offset
251                                )
252{
253    struct drm_lnc_video_getparam_arg arg;
254    unsigned long offset;
255    int ret = 0;
256
257    *bo_offset = 0;
258
259    arg.key = LNC_VIDEO_GETPARAM_RAR_HANDLER_OFFSET;
260    arg.arg = (uint64_t)((unsigned long) & rar_handle);
261    arg.value = (uint64_t)((unsigned long) & offset);
262    ret = drmCommandWriteRead(driver_data->drm_fd, driver_data->getParamIoctlOffset,
263                              &arg, sizeof(arg));
264    if (ret == 0) {
265        *bo_offset = offset;
266
267        return ret;
268    }
269
270    psb__information_message("RAR buffer 0x%08x, get offset failed\n", rar_handle);
271    return ret;
272}
273
274
275static VAStatus psb_buffer_init_rar(psb_driver_data_p driver_data)
276{
277    int ret = 0;
278    RAR_desc_t *rar_rd;
279
280    /* hasn't grab RAR device memory region
281     * grab the whole 8M RAR device memory
282     */
283    driver_data->rar_bo = calloc(1, sizeof(struct psb_buffer_s));
284    if (driver_data->rar_bo == NULL)
285        goto exit_error;
286
287    driver_data->rar_rd = calloc(1, sizeof(RAR_desc_t));
288    if (driver_data->rar_rd == NULL)
289        goto exit_error;
290
291    memset(driver_data->rar_rd, 0, sizeof(RAR_desc_t));
292
293    psb__information_message("Init RAR device\n");
294
295    ret = RAR_init(driver_data->rar_rd);
296    if (ret != 0) {
297        psb__error_message("RAR device init failed\n");
298        goto exit_error;
299    }
300
301    if (psb_buffer_info_rar(driver_data)) {
302        psb__error_message("Get RAR region size failed\n");
303        goto exit_error;
304    }
305
306    psb__information_message("Grab whole camera device memory\n");
307    ret = psb_buffer_create(driver_data, driver_data->rar_size, psb_bt_rar, (psb_buffer_p) driver_data->rar_bo);
308
309    if (ret != VA_STATUS_SUCCESS) {
310        psb__error_message("Grab RAR device memory failed\n");
311        goto exit_error;
312    }
313
314    return VA_STATUS_SUCCESS;
315
316exit_error:
317    rar_rd = driver_data->rar_rd;
318
319    if (rar_rd) {
320        if (rar_rd->mrfd)
321            RAR_fini(driver_data->rar_rd);
322        free(rar_rd);
323    }
324
325    if (driver_data->rar_bo)
326        free(driver_data->rar_bo);
327
328    driver_data->rar_bo = NULL;
329    driver_data->rar_rd = NULL;
330
331    return VA_STATUS_ERROR_ALLOCATION_FAILED;
332}
333
334
335
336/*
337 * Create RAR buffer
338 * Only used when create a protected surface
339 */
340VAStatus psb_buffer_create_rar(psb_driver_data_p driver_data,
341                               unsigned int size,
342                               psb_buffer_p buf
343                              )
344{
345    VAStatus vaStatus;
346    uint32_t rar_handle = 0;
347    unsigned int rar_offset = 0;
348    RAR_desc_t *rar_rd;
349    int ret;
350
351    if (driver_data->rar_rd  == NULL) {
352        vaStatus = psb_buffer_init_rar(driver_data);
353        if (vaStatus != VA_STATUS_SUCCESS) {
354            psb__error_message("RAR init failed!\n");
355            return vaStatus;
356        }
357    }
358
359    rar_rd = driver_data->rar_rd;
360
361    /* Call RAR interface to allocate RAR buffers */
362    ret = RAR_reserve(rar_rd, size, RAR_TYPE_VIDEO, &rar_handle);
363    if (ret != 0) {
364        psb__error_message("RAR reserver memory failed\n");
365        RAR_fini(rar_rd);
366
367        return VA_STATUS_ERROR_UNKNOWN;
368    }
369
370    ret = psb_buffer_offset_rar(driver_data, buf, rar_handle, &rar_offset);
371    if (ret != 0) {
372        psb__error_message("Get buffer offset of RAR device memory failed!\n");
373        return ret;
374    }
375
376    /* reference the global RAR BO */
377    ret = psb_buffer_reference(driver_data, buf, (psb_buffer_p) driver_data->rar_bo);
378    if (ret != VA_STATUS_SUCCESS) {
379        psb__error_message("Reference RAR device memory failed\n");
380        return ret;
381    }
382
383    buf->rar_handle = rar_handle;
384    buf->buffer_ofs = rar_offset;
385
386    /* reference the global RAR buffer, reset buffer type */
387    buf->type = psb_bt_rar_surface; /* need RAR_release */
388
389    psb__information_message("Create RAR buffer, handle 0x%08x, RAR region offset =0x%08x, RAR BO GPU offset hint=0x%08x\n",
390                             rar_handle, rar_offset, wsbmBOOffsetHint(buf->drm_buf));
391
392    return VA_STATUS_SUCCESS;
393}
394
395
396/*
397 * Destroy RAR buffer
398 */
399VAStatus psb_buffer_destroy_rar(psb_driver_data_p driver_data,
400                                psb_buffer_p buf
401                               )
402{
403    RAR_desc_t *rar_rd;
404    int ret;
405
406    ASSERT(driver_data->rar_rd);
407
408    if (buf->type == psb_bt_rar_slice) {
409        psb__information_message("return RAR slice buffer to application\n");
410        buf->rar_handle = 0;
411        return VA_STATUS_SUCCESS;
412    }
413
414
415    rar_rd = driver_data->rar_rd;
416
417    ret = RAR_release(rar_rd, buf->rar_handle);
418    if (ret != 0)
419        psb__error_message("RAR release memory failed\n");
420
421    buf->rar_handle = 0;
422
423    return VA_STATUS_SUCCESS;
424}
425
426/*
427 * Reference one RAR buffer from handle
428 * only used to reference a slice RAR buffer which is created outside of video driver
429 */
430VAStatus psb_buffer_reference_rar(psb_driver_data_p driver_data,
431                                  uint32_t rar_handle,
432                                  psb_buffer_p buf
433                                 )
434{
435    VAStatus vaStatus;
436    unsigned int rar_offset = 0;
437    int ret;
438
439    if (driver_data->rar_rd  == NULL) {
440        vaStatus = psb_buffer_init_rar(driver_data);
441        if (vaStatus != VA_STATUS_SUCCESS) {
442            psb__error_message("RAR init failed!\n");
443            return vaStatus;
444        }
445    }
446
447    /* don't need to assign the handle to buffer
448     * so that when destroy the buffer, we just
449     * need to unreference
450     */
451    /* buf->rar_handle = rar_handle; */
452
453    ret = psb_buffer_offset_rar(driver_data, buf, rar_handle, &rar_offset);
454    if (ret != VA_STATUS_SUCCESS) {
455        psb__error_message("Get surfae offset of RAR device memory failed!\n");
456        return ret;
457    }
458
459    /* reference the global RAR BO */
460    ret = psb_buffer_reference(driver_data, buf, (psb_buffer_p) driver_data->rar_bo);
461    if (ret != VA_STATUS_SUCCESS) {
462        psb__error_message("Reference RAR device memory failed\n");
463        return ret;
464    }
465
466    buf->rar_handle = rar_handle;
467    buf->buffer_ofs = rar_offset;
468    /* reference the global RAR buffer, reset buffer type */
469    buf->type = psb_bt_rar_slice; /* don't need to RAR_release */
470
471    psb__information_message("Reference RAR buffer, handle 0x%08x, RAR region offset =0x%08x, RAR BO GPU offset hint=0x%08x\n",
472                             rar_handle, rar_offset, wsbmBOOffsetHint(buf->drm_buf));
473
474    return VA_STATUS_SUCCESS;
475}
476