Home | History | Annotate | Download | only in src
      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 (at) intel.com>
     26  *    Forrest Zhang  <forrest.zhang (at) 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
     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 
     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 
     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  */
     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  */
    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  */
    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
    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
    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  */
    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